JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 62
  • Score
    100M100P100Q55781F
  • License MIT

Protect your users from harmful content. TypeScript SDK for Vettly.

Package Exports

  • @vettly/sdk

Readme

@vettly/sdk

Don't let one bad post kill your startup. Content moderation API for text, images, and video.

Installation

npm install @vettly/sdk

Quick Start

import { createClient } from '@vettly/sdk'

const client = createClient('sk_live_...')

const result = await client.check({
  content: 'User-generated text',
  policyId: 'community-safe'
})

if (result.action === 'block') {
  // Content blocked
}

Get Your API Key

  1. Sign up at vettly.dev
  2. Go to Dashboard → API Keys
  3. Create and copy your key

Features

  • Text, images, video - One unified API for all content types
  • Custom policies - Define thresholds in YAML
  • Webhooks - Get notified when content is flagged
  • Dashboard - Monitor decisions and export logs
  • Automatic retries - Exponential backoff for rate limits and server errors
  • TypeScript - Full type safety with typed errors

Text Moderation

const result = await client.check({
  content: 'User-generated text',
  policyId: 'community-safe',
  contentType: 'text'
})

console.log(result.action)     // 'allow' | 'warn' | 'flag' | 'block'
console.log(result.categories) // Array of { category, score, triggered }
console.log(result.decisionId) // UUID for audit trail

Image Moderation

// From URL
const result = await client.checkImage(
  'https://example.com/image.jpg',
  { policyId: 'strict' }
)

// From base64
const result = await client.checkImage(
  'data:image/jpeg;base64,/9j/4AAQ...',
  { policyId: 'strict' }
)

Idempotency

Prevent duplicate processing with request IDs:

const result = await client.check(
  { content: 'Hello', policyId: 'default' },
  { requestId: 'unique-request-id-123' }
)

Error Handling

The SDK provides typed errors for better error handling:

import {
  VettlyAuthError,
  VettlyRateLimitError,
  VettlyQuotaError,
  VettlyValidationError
} from '@vettly/sdk'

try {
  await client.check({ content: 'test', policyId: 'default' })
} catch (error) {
  if (error instanceof VettlyAuthError) {
    console.log('Invalid API key')
  } else if (error instanceof VettlyRateLimitError) {
    console.log(`Rate limited. Retry after ${error.retryAfter}s`)
  } else if (error instanceof VettlyQuotaError) {
    console.log(`Quota exceeded: ${error.quota?.used}/${error.quota?.limit}`)
  }
}

Webhook Signature Verification

Verify webhook signatures to ensure authenticity:

import { verifyWebhookSignature, constructWebhookEvent } from '@vettly/sdk'

app.post('/webhooks/vettly', async (req, res) => {
  const signature = req.headers['x-vettly-signature']
  const payload = req.rawBody // Make sure to get raw body as string

  const isValid = await verifyWebhookSignature(payload, signature, webhookSecret)

  if (!isValid) {
    return res.status(401).send('Invalid signature')
  }

  const event = constructWebhookEvent(payload)

  if (event.type === 'decision.blocked') {
    // Handle blocked content
  }

  res.status(200).send('OK')
})

Configuration

import { ModerationClient } from '@vettly/sdk'

const client = new ModerationClient({
  apiKey: 'sk_live_...',
  apiUrl: 'https://api.vettly.dev', // Optional: custom API URL
  timeout: 30000,                    // Optional: request timeout in ms (default: 30000)
  maxRetries: 3,                     // Optional: max retries for failures (default: 3)
  retryDelay: 1000,                  // Optional: base delay for backoff in ms (default: 1000)
})

Express Middleware

import { createClient, moderateContent } from '@vettly/sdk'

const client = createClient('sk_live_...')

app.post('/comments',
  moderateContent({
    client,
    policyId: 'community-safe',
    field: 'body.comment' // Optional: path to content field
  }),
  (req, res) => {
    // Content is safe, proceed with your logic
  }
)

Response Format

{
  "decisionId": "550e8400-e29b-41d4-a716-446655440000",
  "action": "block",
  "safe": false,
  "flagged": true,
  "categories": [
    { "category": "hate_speech", "score": 0.91, "triggered": true },
    { "category": "harassment", "score": 0.08, "triggered": false }
  ],
  "latency": 147
}

Pricing

Plan Price Text Images Videos
Developer Free 2,000/mo 100/mo 25/mo
Growth $49/mo 50,000/mo 5,000/mo 1,000/mo
Pro $149/mo 250,000/mo 25,000/mo 5,000/mo
Enterprise Custom Unlimited Unlimited Unlimited