Vettly REST API

Content moderation REST API for evaluating text, images, and video against policies, with batch checks, webhooks, and OpenClaw Guardrails endpoints for agent skill vetting and action authorization.

Operations 4

GET /health Health check #
GET /metrics Prometheus metrics #
POST /v1/check Check content for moderation #
POST /v1/check/dry-run Test policy (dry run) #

Documentation

Specifications

Other Resources

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/vettly-rest-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

vettly-content-moderation-openapi.json Raw ↑
{"openapi":"3.0.3","info":{"title":"Vettly Content Moderation API","version":"0.3.0","description":"\n# Vettly Content Moderation API\n\nContent moderation API for apps with user-generated content. Moderate text, images, and video in one API call. Define moderation policies in plain-English YAML. Every decision is auditable.\n\nUse Vettly when you need to check user-generated content (comments, messages, uploads, bios, reviews) for safety before showing it to other users.\n\n## Key Features\n\n- **Text, image, and video moderation** in a single API\n- **Custom policies in YAML** - define what to block, flag, or allow per category\n- **Sub-500ms latency** for real-time moderation\n- **Audit trail** - every decision has a unique ID for compliance\n- **Appeals workflow** - built-in user appeal handling\n- **Webhooks** - get notified on block/flag decisions\n- **Batch processing** - check up to 100 items at once\n\n## Authentication\n\nAll endpoints (except /health) require a Bearer token:\n\n```\nAuthorization: Bearer vettly_live_your_api_key_here\n```\n\nAPI keys: `vettly_live_` for production, `vettly_test_` for testing.\n\n## Rate Limits\n\n| Tier | Requests/Minute | Requests/Hour |\n|------|----------------|---------------|\n| Free | 10 | 500 |\n| Starter | 60 | 5,000 |\n| Growth | 120 | 15,000 |\n| Pro  | 300 | 30,000 |\n| Enterprise | 1,000 | 200,000 |\n\nRate limit headers: `X-RateLimit-Limit-Minute`, `X-RateLimit-Remaining-Minute`, `X-RateLimit-Reset-Minute`\n\n## Error Format\n\n```json\n{\n  \"error\": \"Human-readable message\",\n  \"code\": \"ERROR_CODE\"\n}\n```\n\nCodes: `MISSING_AUTH`, `INVALID_API_KEY`, `RATE_LIMIT_EXCEEDED`, `QUOTA_EXCEEDED`, `MODERATION_ERROR`\n    ","contact":{"name":"Vettly Support","url":"https://vettly.dev"},"license":{"name":"Proprietary","url":"https://vettly.dev/legal/terms"}},"servers":[{"url":"https://api.vettly.dev","description":"Production"},{"url":"http://localhost:3000","description":"Development"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Key","description":"Enter your API key starting with vettly_live_ or vettly_test_"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable error message"},"code":{"type":"string","description":"Machine-readable error code"},"message":{"type":"string","description":"Additional error details"}},"required":["error","code"]},"CheckRequest":{"type":"object","description":"Request body for content moderation. Send user-generated content (text, image URL, or video URL) and a policy ID to get an allow/flag/block decision.","properties":{"content":{"type":"string","description":"The user-generated content to moderate. For text, send the raw string. For images, send a URL or base64 data URI. For video, send a URL.","minLength":1,"maxLength":100000,"example":"This is a sample text to moderate"},"policyId":{"type":"string","description":"ID of the moderation policy to evaluate against. Use \"default\" if you have not created a custom policy.","example":"default"},"contentType":{"type":"string","enum":["text","image","video"],"description":"Type of content. Determines which AI models are used for scoring.","default":"text"},"requestId":{"type":"string","description":"Idempotency key. If you send the same requestId twice, you get the cached result instead of a duplicate check.","example":"req_abc123"},"metadata":{"type":"object","description":"Attach context like userId or source. Stored with the decision for audit purposes.","additionalProperties":true,"example":{"userId":"user_123","source":"chat"}}},"required":["content","policyId"]},"CheckResponse":{"type":"object","description":"Moderation decision. Contains the action (allow/flag/block), category scores, and a decision ID for audit trail.","properties":{"decisionId":{"type":"string","description":"Unique decision ID for audit trail. Use this to look up the decision later or for appeals.","example":"dec_abc123"},"safe":{"type":"boolean","description":"true if no category thresholds were exceeded"},"flagged":{"type":"boolean","description":"true if content needs human review"},"action":{"type":"string","enum":["allow","review","block"],"description":"What to do with this content: allow it, queue for review, or block it"},"categories":{"type":"array","description":"Category scores from moderation provider","items":{"type":"object","properties":{"category":{"type":"string","example":"hate_speech"},"score":{"type":"number","example":0.85},"triggered":{"type":"boolean","example":true}}}},"provider":{"type":"string","description":"Provider used for moderation","example":"openai"},"latency":{"type":"number","description":"Total request latency in milliseconds","example":245},"cost":{"type":"number","description":"Estimated cost in USD","example":0.001},"requestId":{"type":"string","description":"Your provided requestId (if any)","example":"req_abc123"},"cached":{"type":"boolean","description":"Whether this was a cached response (idempotency)"}},"required":["decisionId","safe","flagged","action","categories","provider","latency","cost"]},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"],"description":"Overall system health status"},"version":{"type":"string","description":"API version","example":"0.3.0"},"timestamp":{"type":"string","format":"date-time","description":"Current timestamp"},"providers":{"type":"array","items":{"type":"string"},"description":"Available moderation providers","example":["openai","mock","fallback"]},"checks":{"type":"object","properties":{"database":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail"]},"message":{"type":"string"},"latency":{"type":"number"}}},"providers":{"type":"object","properties":{"status":{"type":"string","enum":["pass","fail"]},"message":{"type":"string"}}}}}},"required":["status","version","timestamp","providers","checks"]}}},"paths":{"/health":{"get":{"summary":"Health check","description":"Check API health and verify dependencies (database, providers)","operationId":"getHealth","tags":["System"],"responses":{"200":{"description":"System is healthy or degraded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"503":{"description":"System is unhealthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/metrics":{"get":{"summary":"Prometheus metrics","description":"Get Prometheus-formatted metrics for monitoring","operationId":"getMetrics","tags":["System"],"responses":{"200":{"description":"Prometheus metrics","content":{"text/plain":{"schema":{"type":"string","example":"# HELP http_requests_total Total number of HTTP requests\n# TYPE http_requests_total counter\nhttp_requests_total{method=\"GET\",route=\"/health\",status=\"200\"} 42"}}}}}}},"/v1/check":{"post":{"summary":"Check content for moderation","description":"Send user-generated content (text, image, or video) and get an allow/flag/block decision based on your policy. This is the primary endpoint for content moderation. Returns category scores, a decision action, and a decision ID for audit trail.","operationId":"checkContent","tags":["Moderation"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckRequest"},"examples":{"textModeration":{"summary":"Text moderation","value":{"content":"This is a sample text to moderate","policyId":"default-policy","contentType":"text"}},"imageModeration":{"summary":"Image moderation","value":{"content":"https://example.com/image.jpg","policyId":"default-policy","contentType":"image"}},"withIdempotency":{"summary":"With idempotency key","value":{"content":"This is a sample text","policyId":"default-policy","requestId":"req_unique_123","metadata":{"userId":"user_123","source":"chat"}}}}}}},"responses":{"200":{"description":"Moderation decision","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckResponse"}}},"headers":{"X-Request-ID":{"description":"Request tracking ID","schema":{"type":"string"}},"X-RateLimit-Limit-Minute":{"description":"Rate limit per minute","schema":{"type":"integer"}},"X-RateLimit-Remaining-Minute":{"description":"Remaining requests this minute","schema":{"type":"integer"}}}},"400":{"description":"Invalid request (validation error)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized (missing or invalid API key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Policy not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds until rate limit resets","schema":{"type":"integer"}}}},"500":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/check/dry-run":{"post":{"summary":"Test policy (dry run)","description":"Test a moderation policy with mock scores without saving results","operationId":"dryRunCheck","tags":["Moderation"],"security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CheckRequest"},{"type":"object","properties":{"mockScores":{"type":"object","description":"Mock category scores for testing","additionalProperties":{"type":"number"},"example":{"hate_speech":0.9,"violence":0.3}}}}]}}}},"responses":{"200":{"description":"Dry run result","content":{"application/json":{"schema":{"type":"object","properties":{"dryRun":{"type":"boolean","example":true},"evaluation":{"type":"object","description":"Policy evaluation result"},"policy":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string"}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Policy not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"tags":[{"name":"System","description":"Health checks and monitoring"},{"name":"Moderation","description":"Content moderation endpoints. Use POST /v1/check to moderate user-generated content (text, images, video) and get allow/flag/block decisions."}]}