API Reference

Marketplace API
Complete Reference

RESTful API for publishing, browsing, installing, and managing agents and tools in the Ferni Marketplace.

Jump to Section

Authentication

All API requests require authentication via HTTP headers. Different endpoints require different authentication levels:

User Authentication

For install, usage, and billing endpoints:

http
x-user-id: user_abc123

Publisher Authentication

For submitting and managing tools/agents:

http
x-publisher-id: pub_xyz789
x-publisher-name: Acme Corp

Example Request

bash
curl https://api.ferni.ai/api/marketplace/browse/tools \
  -H "x-user-id: user_abc123"

Developer API

Create, manage, and publish AI personas through the developer console. All endpoints require Firebase Authentication.

Developer Authentication

Developer API uses Firebase Auth tokens. Get a token after signing in with Google or GitHub:

http
Authorization: Bearer <firebase-id-token>

API Keys

GET /api/v1/developers/keys

List all API keys (prefix only for security).

Response

json
{
  "keys": [
    {
      "id": "key_abc123",
      "name": "Production Key",
      "prefix": "pk_live_abc1****",
      "createdAt": "2026-01-03T10:00:00Z",
      "lastUsedAt": "2026-01-03T15:30:00Z"
    }
  ]
}
POST /api/v1/developers/keys

Create a new API key. The full key is only returned once!

Request Body

json
{
  "name": "Production Key",
  "environment": "live"
}

Response

json
{
  "key": {
    "id": "key_abc123",
    "name": "Production Key",
    "fullKey": "pk_live_abc123def456...",
    "prefix": "pk_live_abc1****",
    "createdAt": "2026-01-03T10:00:00Z"
  },
  "warning": "Store this key securely. It will not be shown again."
}
DELETE /api/v1/developers/keys/:id

Revoke an API key immediately.

Personas

GET /api/v1/developers/personas

List all personas created by the authenticated developer.

Response

json
{
  "personas": [
    {
      "id": "persona_abc123",
      "name": "Luna the Coach",
      "tagline": "Your thoughtful companion for growth",
      "status": "draft",
      "category": "coaching",
      "createdAt": "2026-01-03T10:00:00Z",
      "updatedAt": "2026-01-03T15:30:00Z"
    }
  ]
}
POST /api/v1/developers/personas

Create a new persona draft.

Request Body (Persona Manifest)

json
{
  "manifest": {
    "identity": {
      "id": "luna-coach",
      "name": "Luna the Coach",
      "tagline": "Your thoughtful companion for growth",
      "description": "A warm, insightful life coach...",
      "aliases": ["Luna", "Coach Luna"]
    },
    "voice": {
      "provider": "cartesia",
      "voice_id": "a0e99841-438c-4a64-b679-ae501e7d6091"
    },
    "personality": {
      "warmth": 0.85,
      "humor_level": 0.6,
      "directness": 0.7,
      "formality": 0.3,
      "traits": ["empathetic", "encouraging", "insightful"]
    },
    "knowledge": {
      "category": "coaching",
      "domains": ["life-coaching", "personal-growth"],
      "expertise_tags": ["goal-setting", "habits", "motivation"],
      "out_of_scope_topics": ["medical-advice", "legal-advice"]
    },
    "behaviors": {
      "greetings": ["Hey! Ready to make some progress today?"],
      "backchannels": ["mm-hmm", "I hear you", "go on"],
      "thinking_sounds": ["hmm", "let me think..."]
    }
  }
}
PUT /api/v1/developers/personas/:id

Update a draft persona. Only drafts and rejected personas can be updated.

POST /api/v1/developers/personas/:id/validate

Validate a persona manifest before submission.

Response

json
{
  "valid": true,
  "errors": [],
  "warnings": [
    "Consider adding more greeting variations for natural conversation"
  ]
}
POST /api/v1/developers/personas/:id/submit

Submit a persona for marketplace review. Must pass validation first.

Response

json
{
  "success": true,
  "status": "submitted",
  "message": "Your persona has been submitted for review. This typically takes 2-5 business days."
}
DELETE /api/v1/developers/personas/:id

Delete a persona. Published personas cannot be deleted (use unpublish instead).

Voices

GET /api/v1/developers/voices

List curated Cartesia voices available for personas.

Query Parameters

  • gender - Filter by gender (male, female, neutral)
  • category - Filter by category (conversational, professional, etc.)

Response

json
{
  "voices": [
    {
      "id": "a0e99841-438c-4a64-b679-ae501e7d6091",
      "name": "Sarah",
      "description": "Warm and friendly female voice, perfect for coaching",
      "gender": "female",
      "category": "conversational",
      "tags": ["warm", "friendly", "coach"]
    }
  ]
}
POST /api/v1/developers/voices/preview

Generate an audio preview of a voice with custom text.

Request Body

json
{
  "voice_id": "a0e99841-438c-4a64-b679-ae501e7d6091",
  "text": "Hey! I'm so glad you're here. Let's talk about what's on your mind."
}

Response

json
{
  "preview": {
    "audioUrl": "data:audio/mp3;base64,SUQzBAAAAAAAI1RTU0UAAAAP...",
    "duration": 3.2,
    "text": "Hey! I'm so glad you're here..."
  }
}

Persona Lifecycle

draft submitted approved published

Rejected personas can be edited and resubmitted. Published personas appear in the marketplace.

Analytics

GET /api/v1/developers/analytics/overview

Get summary statistics with comparison to previous period.

Query Parameters

  • period - Time period: day, week, month, or year (default: week)

Response

json
{
  "overview": {
    "totalApiCalls": 12500,
    "totalApiCallsChange": 15,
    "uniqueUsers": 340,
    "uniqueUsersChange": 8,
    "activePersonas": 5,
    "activePersonasChange": 0,
    "errorRate": 0.5,
    "errorRateChange": -12,
    "avgResponseTime": 245,
    "avgResponseTimeChange": -5
  }
}
GET /api/v1/developers/analytics/usage

Get API call volume over time for charting.

Response

json
{
  "usage": [
    { "date": "2026-01-01", "apiCalls": 1850, "uniqueUsers": 42, "errors": 5 },
    { "date": "2026-01-02", "apiCalls": 2100, "uniqueUsers": 48, "errors": 3 }
  ]
}
GET /api/v1/developers/analytics/personas

Get per-persona usage breakdown.

Response

json
{
  "personas": [
    {
      "personaId": "persona_abc123",
      "personaName": "Luna the Coach",
      "totalCalls": 5200,
      "avgSessionDuration": 180000,
      "uniqueUsers": 150
    }
  ]
}
GET /api/v1/developers/analytics/errors

Get error breakdown by type.

Response

json
{
  "errors": [
    {
      "code": "RATE_LIMIT_EXCEEDED",
      "message": "API rate limit exceeded",
      "count": 23,
      "lastOccurred": "2026-01-03T15:30:00Z"
    }
  ]
}

Publisher API

Submit, update, and manage your published tools and agents.

POST /api/marketplace/publisher/submit

Submit a new tool or agent for marketplace review.

Request Body

json
{
  "type": "tool",
  "manifest": {
    "id": "my-habit-tracker",
    "name": "Habit Tracker Pro",
    "version": "1.0.0",
    "publisher": {
      "id": "pub_xyz789",
      "name": "Acme Corp"
    },
    "description": {
      "short": "Track daily habits with AI insights",
      "long": "A comprehensive habit tracking tool..."
    },
    "execution": {
      "runtime": {
        "type": "nodejs",
        "version": "18"
      }
    },
    "interface": {
      "llmDescription": "Tracks user habits and provides insights"
    }
  }
}

Example Request

bash
curl -X POST https://api.ferni.ai/api/marketplace/publisher/submit \
  -H "x-publisher-id: pub_xyz789" \
  -H "x-publisher-name: Acme Corp" \
  -H "Content-Type: application/json" \
  -d @tool-manifest.json

Response (200 OK)

json
{
  "success": true,
  "itemId": "my-habit-tracker",
  "status": "pending_review",
  "reviewNotes": "Your submission is being reviewed. This typically takes 2-5 business days."
}
GET /api/marketplace/publisher/items

List all items published by your account.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/publisher/items \
  -H "x-publisher-id: pub_xyz789" \
  -H "x-publisher-name: Acme Corp"

Response (200 OK)

json
{
  "items": [
    {
      "id": "my-habit-tracker",
      "name": "Habit Tracker Pro",
      "type": "tool",
      "version": "1.0.0",
      "status": "approved",
      "trustLevel": "community",
      "publishedAt": "2025-01-15T10:30:00Z"
    }
  ],
  "totalCount": 1
}
GET /api/marketplace/publisher/profile

Get your publisher profile and statistics.

Response (200 OK)

json
{
  "publisherId": "pub_xyz789",
  "publisherName": "Acme Corp",
  "verified": true,
  "stats": {
    "totalTools": 5,
    "totalAgents": 2,
    "approvedItems": 6,
    "pendingItems": 1
  }
}
GET /api/marketplace/publisher/:id/analytics

Get detailed analytics for a specific item.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/publisher/my-habit-tracker/analytics \
  -H "x-publisher-id: pub_xyz789" \
  -H "x-publisher-name: Acme Corp"

Response (200 OK)

json
{
  "itemId": "my-habit-tracker",
  "period": "30d",
  "metrics": {
    "totalInstalls": 150,
    "activeInstalls": 120,
    "totalExecutions": 2450,
    "successRate": 98.5,
    "avgExecutionTimeMs": 125,
    "errorCount": 37,
    "uniqueUsers": 115
  },
  "revenue": {
    "totalCents": 15000,
    "periodCents": 5000,
    "currency": "USD"
  },
  "topErrors": [
    {
      "code": "RATE_LIMIT_EXCEEDED",
      "count": 25,
      "lastOccurred": "2025-01-14T18:30:00Z"
    }
  ]
}
PUT /api/marketplace/publisher/:id

Update an existing submission with new manifest data.

Example Request

bash
curl -X PUT https://api.ferni.ai/api/marketplace/publisher/my-habit-tracker \
  -H "x-publisher-id: pub_xyz789" \
  -H "x-publisher-name: Acme Corp" \
  -H "Content-Type: application/json" \
  -d @updated-manifest.json

Response (200 OK)

json
{
  "success": true,
  "itemId": "my-habit-tracker",
  "status": "approved"
}
DELETE /api/marketplace/publisher/:id

Delete a submission from the marketplace. Existing installations continue to work for 30 days.

Example Request

bash
curl -X DELETE https://api.ferni.ai/api/marketplace/publisher/my-habit-tracker \
  -H "x-publisher-id: pub_xyz789" \
  -H "x-publisher-name: Acme Corp"

Response (200 OK)

json
{
  "success": true,
  "message": "Item scheduled for removal. Existing installations will continue to work for 30 days."
}

Browse API

Discover and retrieve information about tools and agents in the marketplace.

GET /api/marketplace/browse/tools

List all available tools in the marketplace.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/browse/tools

Response (200 OK)

json
{
  "tools": [
    {
      "id": "habit-tracker-pro",
      "name": "Habit Tracker Pro",
      "description": "Track daily habits with AI insights",
      "version": "1.0.0",
      "publisher": {
        "id": "pub_xyz789",
        "name": "Acme Corp"
      },
      "trustLevel": "community",
      "verified": true
    }
  ],
  "totalCount": 1
}
GET /api/marketplace/browse/agents

List all available agents in the marketplace.

Response (200 OK)

json
{
  "agents": [
    {
      "id": "wellness-coach",
      "name": "wellness-coach",
      "displayName": "Luna the Wellness Coach",
      "description": "Your guide to healthier living",
      "version": "2.1.0",
      "publisher": {
        "id": "pub_xyz789",
        "name": "Acme Corp"
      },
      "trustLevel": "verified",
      "verified": true
    }
  ],
  "totalCount": 1
}
GET /api/marketplace/browse/tools/:id

Get detailed information about a specific tool.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/browse/tools/habit-tracker-pro

Response (200 OK)

json
{
  "tool": {
    "id": "habit-tracker-pro",
    "name": "Habit Tracker Pro",
    "version": "1.0.0",
    "description": {
      "short": "Track daily habits with AI insights",
      "long": "A comprehensive habit tracking tool with AI-powered analytics..."
    },
    "publisher": {
      "id": "pub_xyz789",
      "name": "Acme Corp"
    },
    "execution": {
      "runtime": {
        "type": "nodejs",
        "version": "18"
      }
    },
    "interface": {
      "llmDescription": "Tracks user habits and provides insights"
    },
    "verification": {
      "trustLevel": "community",
      "verified": true,
      "verifiedAt": "2025-01-10T12:00:00Z"
    }
  }
}
GET /api/marketplace/browse/agents/:id

Get detailed information about a specific agent.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/browse/agents/wellness-coach

Install API

Install, uninstall, and manage marketplace items.

POST /api/marketplace/install/tool

Install a tool for the authenticated user.

Request Body

json
{
  "toolId": "habit-tracker-pro",
  "grantedPermissions": ["user:read", "user:write"]
}

Example Request

bash
curl -X POST https://api.ferni.ai/api/marketplace/install/tool \
  -H "x-user-id: user_abc123" \
  -H "Content-Type: application/json" \
  -d '{"toolId":"habit-tracker-pro","grantedPermissions":["user:read","user:write"]}'

Response (200 OK)

json
{
  "success": true,
  "installation": {
    "id": "inst_def456",
    "toolId": "habit-tracker-pro",
    "installedAt": "2025-01-14T15:30:00Z"
  }
}
POST /api/marketplace/install/agent

Install an agent for the authenticated user.

Request Body

json
{
  "agentId": "wellness-coach",
  "grantedPermissions": ["user:read"]
}

Response (200 OK)

json
{
  "success": true,
  "installation": {
    "id": "inst_ghi789",
    "agentId": "wellness-coach",
    "installedAt": "2025-01-14T15:32:00Z"
  }
}
DELETE /api/marketplace/install/tool/:id

Uninstall a tool.

Example Request

bash
curl -X DELETE https://api.ferni.ai/api/marketplace/install/tool/habit-tracker-pro \
  -H "x-user-id: user_abc123"

Response (200 OK)

json
{
  "success": true
}
DELETE /api/marketplace/install/agent/:id

Uninstall an agent.

Example Request

bash
curl -X DELETE https://api.ferni.ai/api/marketplace/install/agent/wellness-coach \
  -H "x-user-id: user_abc123"
GET /api/marketplace/install/list

List all installations for the authenticated user.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/install/list \
  -H "x-user-id: user_abc123"

Response (200 OK)

json
{
  "installations": [
    {
      "id": "inst_def456",
      "itemId": "habit-tracker-pro",
      "itemType": "tool",
      "installedAt": "2025-01-14T15:30:00Z",
      "status": "active"
    },
    {
      "id": "inst_ghi789",
      "itemId": "wellness-coach",
      "itemType": "agent",
      "installedAt": "2025-01-14T15:32:00Z",
      "status": "active"
    }
  ],
  "totalCount": 2
}

Usage & Billing API

Track usage, check quotas, and retrieve billing information.

GET /api/marketplace/usage/:itemId

Get usage statistics for a specific item.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/usage/habit-tracker-pro \
  -H "x-user-id: user_abc123" \
  -H "x-subscription-tier: pro"

Response (200 OK)

json
{
  "itemId": "habit-tracker-pro",
  "period": "2025-01",
  "userId": "user_abc123",
  "tier": "pro",
  "totals": {
    "executions": 45,
    "executionTimeMs": 12500,
    "quotaUsed": 45,
    "quotaLimit": 1000
  },
  "breakdown": [
    {
      "date": "2025-01-14",
      "executions": 5,
      "executionTimeMs": 1250
    }
  ]
}
GET /api/marketplace/usage/summary

Get aggregated usage across all installed items.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/usage/summary \
  -H "x-user-id: user_abc123" \
  -H "x-subscription-tier: pro"

Response (200 OK)

json
{
  "period": "2025-01",
  "userId": "user_abc123",
  "tier": "pro",
  "aggregate": {
    "totalExecutions": 87,
    "totalTimeMs": 24500,
    "itemCount": 2
  },
  "items": [
    {
      "itemId": "habit-tracker-pro",
      "totals": {
        "executions": 45,
        "executionTimeMs": 12500,
        "quotaUsed": 45,
        "quotaLimit": 1000
      }
    }
  ]
}
GET /api/marketplace/quota/check/:itemId

Check if user has available quota to execute an item.

Example Request

bash
curl https://api.ferni.ai/api/marketplace/quota/check/habit-tracker-pro \
  -H "x-user-id: user_abc123" \
  -H "x-subscription-tier: pro"

Response (200 OK)

json
{
  "allowed": true,
  "reason": null,
  "quotaUsed": 45,
  "quotaLimit": 1000,
  "remainingQuota": 955
}

Response (200 OK - Quota Exceeded)

json
{
  "allowed": false,
  "reason": "Monthly quota exceeded. Upgrade to Pro for higher limits.",
  "quotaUsed": 100,
  "quotaLimit": 100,
  "remainingQuota": 0
}

Error Codes

The API uses standard HTTP status codes and returns error details in JSON format.

HTTP Status Codes

Code Meaning Description
200 OK Request successful
400 Bad Request Invalid request body or parameters
401 Unauthorized Missing or invalid authentication
403 Forbidden Not authorized to access resource
404 Not Found Resource does not exist
500 Internal Server Error Server error occurred

Error Response Format

json
{
  "success": false,
  "error": "Validation failed",
  "validationErrors": [
    "Tool ID is required",
    "Valid semantic version required (e.g., 1.0.0)"
  ]
}

Common Error Scenarios

Missing Authentication

401 Unauthorized - Include x-user-id or x-publisher-id header

Publisher ID Mismatch

403 Forbidden - Publisher ID in manifest must match authenticated publisher

Item Not Found

404 Not Found - Requested tool or agent does not exist

Invalid Manifest

400 Bad Request - Check validationErrors array for specific issues

Need Help?