📊 EmoVision API

Enterprise-Grade Video Honesty Analysis API

🚀 Getting Started

Welcome to the EmoVision API! This API allows you to integrate advanced video honesty analysis, emotion detection, and body language insights into your applications.

Overview

EmoVision provides a RESTful API that enables developers to:

Quick Start

  1. Create an organization and generate an API key from your dashboard
  2. Store your API key securely (it's only shown once)
  3. Make authenticated requests using the Authorization: Bearer YOUR_API_KEY header
  4. Upload videos for analysis and retrieve results
  5. Set up webhooks to receive real-time notifications
💡 Base URL: All API requests should be made to https://your-domain.com/api/v1/

🔐 Authentication

API Keys

All API requests require an API key. Include your API key in the Authorization header:

Authorization: Bearer ek_live_your_api_key_here

Generating API Keys

Generate API keys through the web interface at /api/keys/generate (requires admin or manager role):

curl -X POST https://your-domain.com/api/keys/generate \
  -H "Content-Type: application/json" \
  -H "Cookie: session_token=YOUR_SESSION_TOKEN" \
  -d '{
    "org_id": 1,
    "name": "Production API Key",
    "rate_limit_per_minute": 60
  }'
import requests

response = requests.post(
    'https://your-domain.com/api/keys/generate',
    headers={'Cookie': 'session_token=YOUR_SESSION_TOKEN'},
    json={
        'org_id': 1,
        'name': 'Production API Key',
        'rate_limit_per_minute': 60
    }
)

api_key = response.json()['api_key']
print(f"API Key: {api_key}")
# Save this securely - it won't be shown again!
const response = await fetch('https://your-domain.com/api/keys/generate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  credentials: 'include',
  body: JSON.stringify({
    org_id: 1,
    name: 'Production API Key',
    rate_limit_per_minute: 60
  })
});

const data = await response.json();
console.log('API Key:', data.api_key);
// Save this securely - it won't be shown again!
⚠️ Security Warning: API keys are only shown once when generated. Store them securely and never commit them to version control.

📡 API Endpoints

POST 🔑 Auth Required /api/v1/analyze

Upload a video file for comprehensive honesty and emotion analysis.

Request

Header Value
Authorization Bearer YOUR_API_KEY
Content-Type multipart/form-data
Parameter Type Required Description
video File Yes Video file (MP4, AVI, MOV, WebM)
metadata JSON String No Optional metadata for the recording

Response

{
  "recording_id": "rec_a1b2c3d4e5f6",
  "duration_minutes": 5.25,
  "overall_honesty_score": 78.5,
  "emotion_breakdown": {
    "happy": 0.35,
    "neutral": 0.45,
    "surprised": 0.12,
    "sad": 0.08
  },
  "key_moments": [
    {
      "timestamp_ms": 45000,
      "type": "honesty_drop",
      "score": 0.45
    }
  ],
  "cost_usd": 1.31,
  "status": "completed"
}

Example Request

curl -X POST https://your-domain.com/api/v1/analyze \
  -H "Authorization: Bearer ek_live_your_api_key" \
  -F "video=@interview.mp4" \
  -F 'metadata={"candidate": "John Doe", "position": "Senior Engineer"}'
import requests

api_key = "ek_live_your_api_key"

with open('interview.mp4', 'rb') as video_file:
    response = requests.post(
        'https://your-domain.com/api/v1/analyze',
        headers={'Authorization': f'Bearer {api_key}'},
        files={'video': video_file},
        data={'metadata': '{"candidate": "John Doe", "position": "Senior Engineer"}'}
    )

result = response.json()
print(f"Honesty Score: {result['overall_honesty_score']}%")
print(f"Recording ID: {result['recording_id']}")
const formData = new FormData();
formData.append('video', videoFile);
formData.append('metadata', JSON.stringify({
  candidate: 'John Doe',
  position: 'Senior Engineer'
}));

const response = await fetch('https://your-domain.com/api/v1/analyze', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer ek_live_your_api_key'
  },
  body: formData
});

const result = await response.json();
console.log(`Honesty Score: ${result.overall_honesty_score}%`);

GET 🔑 Auth Required /api/v1/recordings

List all recordings for the authenticated organization.

Query Parameters

Parameter Type Default Description
page integer 1 Page number for pagination
per_page integer 20 Results per page (max 100)
status string all Filter by status: completed, processing, failed

GET 🔑 Auth Required /api/v1/recordings/{id}

Get detailed analysis results for a specific recording.

GET 🔑 Auth Required /api/v1/usage

Get current month's usage statistics and costs.

Response

{
  "month": "2025-01",
  "total_analyses": 150,
  "total_minutes_analyzed": 487.5,
  "total_cost_usd": 121.88,
  "rate_limit": {
    "limit": 60,
    "remaining": 45,
    "reset": 1706745600
  }
}

DELETE 🔑 Auth Required /api/v1/recordings/{id}

Delete a recording and all associated analysis data.

⚠️ Warning: This action is irreversible. All analysis data associated with this recording will be permanently deleted.
💡 Pagination: All list endpoints support pagination. Use page and per_page query parameters to navigate through results.

📦 SDKs & Libraries

Python SDK

pip install emotionchat
from emotionchat import EmotionChat

client = EmotionChat(api_key="ek_live_your_api_key")
result = client.analyze("interview.mp4")
print(f"Score: {result.honesty_score}%")

JavaScript/Node.js SDK

npm install @emotionchat/sdk
import { EmotionChat } from '@emotionchat/sdk';

const client = new EmotionChat({ apiKey: 'ek_live_your_api_key' });
const result = await client.analyze('interview.mp4');
console.log(`Score: ${result.honestyScore}%`);

Ruby SDK Coming Soon

Ruby SDK is currently in development. Sign up for notifications.

🔔 Webhooks

Set up webhooks to receive real-time notifications when analysis completes.

Webhook Events

Event Description
analysis.completed Video analysis has finished processing
analysis.failed Video analysis encountered an error
usage.threshold Usage has exceeded a configured threshold

Webhook Payload

{
  "event": "analysis.completed",
  "timestamp": "2025-01-15T10:30:00Z",
  "data": {
    "recording_id": "rec_a1b2c3d4e5f6",
    "overall_honesty_score": 78.5,
    "status": "completed",
    "cost_usd": 1.31
  }
}

Verifying Webhooks

All webhook payloads are signed with HMAC-SHA256. Verify the signature using the X-EmotionChat-Signature header:

import hmac
import hashlib

def verify_webhook(payload, signature, secret):
    expected = hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

# In your Flask endpoint:
@app.route('/webhooks/emotionchat', methods=['POST'])
def handle_webhook():
    payload = request.get_data(as_text=True)
    signature = request.headers.get('X-EmotionChat-Signature')
    
    if not verify_webhook(payload, signature, WEBHOOK_SECRET):
        return 'Invalid signature', 401
    
    # Process webhook event
    return 'OK', 200
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// In your Express endpoint:
app.post('/webhooks/emotionchat', (req, res) => {
  const payload = JSON.stringify(req.body);
  const signature = req.headers['x-emotionchat-signature'];
  
  if (!verifyWebhook(payload, signature, WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process webhook event
  res.status(200).send('OK');
});

Retry Logic

Failed webhook deliveries are retried up to 3 times with exponential backoff:

💡 Best Practice: Return a 200 OK response within 5 seconds to acknowledge receipt. Process the webhook payload asynchronously to avoid timeouts.

⚡ Rate Limits

Default Rate Limit

60 requests per minute

Rate Limit Headers

All API responses include rate limit headers to help you manage your usage:

Header Description
X-RateLimit-Limit Maximum requests allowed per minute
X-RateLimit-Remaining Requests remaining in current window
X-RateLimit-Reset Unix timestamp when the limit resets

Tier-Based Rate Limits

Tier Rate Limit Burst Limit
Free 20 requests/minute 30 requests
Pro 60 requests/minute 100 requests
Premium 300 requests/minute 500 requests
Enterprise Custom Custom
💡 Custom Rate Limits: Contact sales for higher rate limits on enterprise plans.

Rate Limit Exceeded

When you exceed your rate limit, the API returns a 429 Too Many Requests response:

{
  "error": "Rate limit exceeded",
  "retry_after": 42
}

💰 Billing & Pricing

Usage-Based Pricing

Service Rate
Video Analysis (Basic) $0.25 per minute of video
Video Analysis (Advanced) $0.50 per minute of video
API Requests (GET) Included (subject to rate limits)
Webhook Deliveries Free
Data Storage (30 days) Included
✅ Cost Transparency: Every /api/v1/analyze response includes the exact cost for that analysis in the cost_usd field.

Monitoring Usage

Use the /api/v1/usage endpoint to track your monthly consumption and costs in real-time.

💡 Enterprise Pricing: For high-volume usage or custom pricing arrangements, contact our enterprise sales team.

❌ Error Handling

HTTP Status Codes

Code Meaning
200 Success
201 Created (webhook or resource)
400 Bad Request - Invalid parameters
401 Unauthorized - Invalid or missing API key
403 Forbidden - Insufficient permissions or tier
404 Not Found - Resource doesn't exist
413 Payload Too Large - Video file exceeds size limit
422 Unprocessable Entity - Invalid video format
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error
503 Service Unavailable - Temporary outage

Error Response Format

{
  "error": "Description of what went wrong",
  "code": "INVALID_VIDEO_FORMAT",
  "details": {
    "supported_formats": ["mp4", "avi", "mov", "webm"]
  }
}

Best Practices

📝 API Changelog

Track the evolution of the EmotionChat API and stay updated with new features, improvements, and fixes.

v1.2.0 NEW

October 5, 2025
  • New: Added /api/v1/recordings/{id}/export endpoint for exporting analysis data
  • New: Body language analysis now includes posture confidence scores
  • Improved: Honesty detection accuracy improved by 12% with updated ML models
  • Improved: Webhook delivery retry logic now uses exponential backoff

v1.1.0 IMPROVED

September 15, 2025
  • New: Added support for WebM video format
  • New: Real-time progress updates via Server-Sent Events (SSE)
  • Improved: Video processing speed increased by 40%
  • Fixed: Resolved issue with timezone handling in webhook timestamps

v1.0.0 LAUNCH

August 1, 2025
  • New: Initial API release
  • New: Video analysis with emotion detection
  • New: Honesty scoring algorithm
  • New: Webhook support for real-time notifications
  • New: Usage-based billing and cost tracking
💡 Stay Updated: Subscribe to our developer newsletter at developers@emovision.net to receive updates about API changes and new features.