Official SDKs
Python SDK
hitl-python - Full-featured Python SDK with async support
pip install hitl-pythonNode.js SDK
hitl-js - JavaScript/TypeScript SDK for Node.js and browsers
npm install hitl-jsGo SDK
hitl-go - Go SDK with full type safety and context support
go get github.com/hitl/go-sdkPHP SDK
hitl-php - PHP SDK with PSR-4 autoloading and Composer support
composer require hitl/php-sdkCommunity Libraries
Ruby
hitl-ruby
gem install hitlJava
hitl-java
Maven/Gradle available
Maven/Gradle available
C#
HITL.NET
Install-Package HITLRust
hitl-rs
cargo add hitlSwift
HITLSwift
Swift Package Manager
Swift Package Manager
Kotlin
hitl-kotlin
JVM/Android support
JVM/Android support
Python SDK
Installation
Copy
pip install hitl-python
Quick Start
Copy
from hitl import HITLClient
import asyncio
# Initialize client
client = HITLClient(api_key="your_api_key_here")
# Create a loop
loop = client.loops.create(
name="Content Moderation Team",
description="Review user-generated content",
icon="🔍"
)
print(f"Created loop: {loop.name} ({loop.id})")
# Create a request
request = client.requests.create(
loop_id=loop.id,
request_text="Please review this user comment for appropriate content.",
response_type="single_select",
response_config={
"options": ["Approve", "Reject", "Needs Review"]
},
priority="high"
)
print(f"Created request: {request.id}")
# Wait for completion (blocking)
completed_request = client.requests.wait_for_completion(
request.id,
timeout=300 # 5 minutes
)
print(f"Request completed with response: {completed_request.response_data}")
Async Support
Copy
import asyncio
from hitl import AsyncHITLClient
async def main():
client = AsyncHITLClient(api_key="your_api_key_here")
# Create multiple requests concurrently
tasks = []
for i in range(5):
task = client.requests.create(
loop_id="your_loop_id",
request_text=f"Review request #{i+1}",
response_type="text"
)
tasks.append(task)
# Wait for all requests to be created
requests = await asyncio.gather(*tasks)
print(f"Created {len(requests)} requests")
# Monitor all requests
completion_tasks = [
client.requests.wait_for_completion(req.id, timeout=600)
for req in requests
]
completed = await asyncio.gather(*completion_tasks)
for req in completed:
print(f"Request {req.id}: {req.response_data}")
asyncio.run(main())
Advanced Features
Copy
from hitl import HITLClient, HITLError, RateLimitError, AuthenticationError
client = HITLClient(
api_key="your_api_key_here",
retry_attempts=3,
retry_delay=1.0
)
try:
request = client.requests.create(
loop_id="invalid_loop_id",
request_text="Test request"
)
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after} seconds")
except HITLError as e:
print(f"HITL API error: {e.message}")
Node.js SDK
Installation
Copy
npm install hitl-js
Quick Start
Copy
import { HITLClient } from 'hitl-js';
// Initialize client
const client = new HITLClient({
apiKey: 'your_api_key_here',
baseURL: 'https://api.hitl.sh/v1'
});
async function main() {
try {
// Create a loop
const loop = await client.loops.create({
name: 'Content Moderation Team',
description: 'Review user-generated content',
icon: '🔍'
});
console.log(`Created loop: ${loop.name} (${loop.id})`);
// Create a request
const request = await client.requests.create({
loopId: loop.id,
requestText: 'Please review this user comment for appropriate content.',
responseType: 'single_select',
responseConfig: {
options: ['Approve', 'Reject', 'Needs Review']
},
priority: 'high'
});
console.log(`Created request: ${request.id}`);
// Wait for completion
const completedRequest = await client.requests.waitForCompletion(
request.id,
{ timeout: 300000 } // 5 minutes
);
console.log(`Request completed: ${completedRequest.responseData}`);
} catch (error) {
if (error instanceof client.RateLimitError) {
console.log(`Rate limited. Retry after: ${error.retryAfter}ms`);
} else if (error instanceof client.HITLError) {
console.log(`HITL API error: ${error.message}`);
} else {
console.error('Unexpected error:', error);
}
}
}
main();
TypeScript Support
Copy
import { HITLClient, Loop, Request, RequestStatus } from 'hitl-js';
interface ContentModerationRequest {
content: string;
userId: string;
reportType: 'spam' | 'harassment' | 'inappropriate';
}
class ContentModerationService {
private client: HITLClient;
private moderationLoopId: string;
constructor(apiKey: string, moderationLoopId: string) {
this.client = new HITLClient({ apiKey });
this.moderationLoopId = moderationLoopId;
}
async moderateContent(content: ContentModerationRequest): Promise<string> {
const request = await this.client.requests.create({
loopId: this.moderationLoopId,
requestText: `Review ${content.reportType} report:\n\nContent: ${content.content}\nUser: ${content.userId}`,
responseType: 'single_select',
responseConfig: {
options: ['Approve', 'Remove', 'Warn User', 'Suspend User']
},
priority: content.reportType === 'harassment' ? 'critical' : 'high',
metadata: {
userId: content.userId,
reportType: content.reportType
}
});
// Use webhook or polling to get the result
const result = await this.client.requests.waitForCompletion(request.id, {
timeout: 600000, // 10 minutes
pollInterval: 5000 // Check every 5 seconds
});
return result.responseData as string;
}
async getRequestStats(): Promise<{
total: number;
pending: number;
completed: number;
averageResponseTime: number;
}> {
const requests = await this.client.requests.list({
loopId: this.moderationLoopId,
limit: 100
});
const total = requests.length;
const pending = requests.filter(r => r.status === 'pending').length;
const completed = requests.filter(r => r.status === 'completed').length;
const completedRequests = requests.filter(r => r.responseTimeSeconds);
const averageResponseTime = completedRequests.length > 0
? completedRequests.reduce((sum, r) => sum + r.responseTimeSeconds!, 0) / completedRequests.length
: 0;
return { total, pending, completed, averageResponseTime };
}
}
// Usage
const moderationService = new ContentModerationService(
'your_api_key_here',
'your_moderation_loop_id'
);
// Moderate content
const decision = await moderationService.moderateContent({
content: 'Potentially inappropriate user comment...',
userId: 'user_12345',
reportType: 'inappropriate'
});
console.log(`Moderation decision: ${decision}`);
Express.js Integration
Copy
import express from 'express';
import { HITLClient, WebhookHandler } from 'hitl-js';
const app = express();
const client = new HITLClient({ apiKey: process.env.HITL_API_KEY });
const webhookHandler = new WebhookHandler({ secret: process.env.WEBHOOK_SECRET });
app.use(express.json());
// Webhook endpoint
app.post('/webhook/hitl', async (req, res) => {
try {
const event = webhookHandler.parseEvent(req.body, req.headers);
switch (event.type) {
case 'request.completed':
await handleRequestCompleted(event.data);
break;
case 'request.claimed':
await handleRequestClaimed(event.data);
break;
default:
console.log(`Unhandled event: ${event.type}`);
}
res.json({ status: 'success' });
} catch (error) {
console.error('Webhook error:', error);
res.status(400).json({ error: error.message });
}
});
// API endpoint to create moderation requests
app.post('/api/moderate', async (req, res) => {
try {
const { content, type } = req.body;
const request = await client.requests.create({
loopId: process.env.MODERATION_LOOP_ID,
requestText: `Review ${type}: ${content}`,
responseType: 'single_select',
responseConfig: {
options: ['Approve', 'Reject', 'Flag for Review']
},
priority: 'high'
});
res.json({
requestId: request.id,
status: 'submitted',
estimatedTime: '2-5 minutes'
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
async function handleRequestCompleted(data) {
const { request } = data;
console.log(`Request ${request.id} completed with: ${request.responseData}`);
// Update your database, send notifications, etc.
}
async function handleRequestClaimed(data) {
const { request, reviewer } = data;
console.log(`Request ${request.id} claimed by ${reviewer.email}`);
}
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Go SDK
Installation
Copy
go get github.com/hitl/go-sdk
Quick Start
Copy
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/hitl/go-sdk"
)
func main() {
// Initialize client
client := hitl.NewClient("your_api_key_here")
ctx := context.Background()
// Create a loop
loop, err := client.Loops.Create(ctx, &hitl.CreateLoopRequest{
Name: "Content Moderation Team",
Description: "Review user-generated content",
Icon: "🔍",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created loop: %s (%s)\n", loop.Name, loop.ID)
// Create a request
request, err := client.Requests.Create(ctx, &hitl.CreateRequestRequest{
LoopID: loop.ID,
RequestText: "Please review this user comment for appropriate content.",
ResponseType: hitl.ResponseTypeSingleSelect,
ResponseConfig: &hitl.SingleSelectConfig{
Options: []string{"Approve", "Reject", "Needs Review"},
},
Priority: hitl.PriorityHigh,
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created request: %s\n", request.ID)
// Wait for completion with timeout
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
defer cancel()
completedRequest, err := client.Requests.WaitForCompletion(ctx, request.ID)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Request completed with response: %v\n", completedRequest.ResponseData)
}
Advanced Usage
Copy
package main
import (
"context"
"fmt"
"log"
"sync"
"time"
"github.com/hitl/go-sdk"
)
type ContentModerationService struct {
client *hitl.Client
moderationLoopID string
}
func NewContentModerationService(apiKey, loopID string) *ContentModerationService {
return &ContentModerationService{
client: hitl.NewClient(apiKey),
moderationLoopID: loopID,
}
}
func (cms *ContentModerationService) ModerateContent(ctx context.Context, content string, userID string) (string, error) {
request, err := cms.client.Requests.Create(ctx, &hitl.CreateRequestRequest{
LoopID: cms.moderationLoopID,
RequestText: fmt.Sprintf("Review content from user %s:\n\n%s", userID, content),
ResponseType: hitl.ResponseTypeSingleSelect,
ResponseConfig: &hitl.SingleSelectConfig{
Options: []string{"Approve", "Remove", "Warn User", "Suspend User"},
},
Priority: hitl.PriorityHigh,
Metadata: map[string]interface{}{
"userID": userID,
"contentType": "comment",
},
})
if err != nil {
return "", err
}
// Wait for completion with timeout
completedRequest, err := cms.client.Requests.WaitForCompletion(ctx, request.ID)
if err != nil {
return "", err
}
return completedRequest.ResponseData.(string), nil
}
func (cms *ContentModerationService) ModerateBatch(ctx context.Context, contents []string) ([]string, error) {
var wg sync.WaitGroup
results := make([]string, len(contents))
errors := make([]error, len(contents))
// Process up to 10 items concurrently
semaphore := make(chan struct{}, 10)
for i, content := range contents {
wg.Add(1)
go func(index int, content string) {
defer wg.Done()
semaphore <- struct{}{} // Acquire
defer func() { <-semaphore }() // Release
result, err := cms.ModerateContent(ctx, content, fmt.Sprintf("user_%d", index))
if err != nil {
errors[index] = err
} else {
results[index] = result
}
}(i, content)
}
wg.Wait()
// Check for any errors
for _, err := range errors {
if err != nil {
return nil, err
}
}
return results, nil
}
func main() {
service := NewContentModerationService("your_api_key_here", "your_loop_id")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
// Single content moderation
result, err := service.ModerateContent(ctx, "This is a test comment", "user123")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Moderation result: %s\n", result)
// Batch moderation
contents := []string{
"First comment to review",
"Second comment to review",
"Third comment to review",
}
results, err := service.ModerateBatch(ctx, contents)
if err != nil {
log.Fatal(err)
}
for i, result := range results {
fmt.Printf("Content %d: %s\n", i+1, result)
}
}
PHP SDK
Installation
Copy
composer require hitl/php-sdk
Quick Start
Copy
<?php
require_once 'vendor/autoload.php';
use HITL\Client;
use HITL\Exception\HITLException;
use HITL\Exception\RateLimitException;
// Initialize client
$client = new Client([
'api_key' => 'your_api_key_here',
'base_url' => 'https://api.hitl.sh/v1'
]);
try {
// Create a loop
$loop = $client->loops()->create([
'name' => 'Content Moderation Team',
'description' => 'Review user-generated content',
'icon' => '🔍'
]);
echo "Created loop: {$loop['name']} ({$loop['id']})\n";
// Create a request
$request = $client->requests()->create([
'loop_id' => $loop['id'],
'request_text' => 'Please review this user comment for appropriate content.',
'response_type' => 'single_select',
'response_config' => [
'options' => ['Approve', 'Reject', 'Needs Review']
],
'priority' => 'high'
]);
echo "Created request: {$request['id']}\n";
// Wait for completion (with polling)
$completedRequest = $client->requests()->waitForCompletion($request['id'], [
'timeout' => 300, // 5 minutes
'poll_interval' => 5 // Check every 5 seconds
]);
echo "Request completed with response: {$completedRequest['response_data']}\n";
} catch (RateLimitException $e) {
echo "Rate limited. Retry after: {$e->getRetryAfter()} seconds\n";
} catch (HITLException $e) {
echo "HITL API error: {$e->getMessage()}\n";
} catch (Exception $e) {
echo "Unexpected error: {$e->getMessage()}\n";
}
?>
Laravel Integration
Copy
<?php
// config/hitl.php
return [
'api_key' => env('HITL_API_KEY'),
'base_url' => env('HITL_BASE_URL', 'https://api.hitl.sh/v1'),
'moderation_loop_id' => env('HITL_MODERATION_LOOP_ID'),
];
// app/Services/ContentModerationService.php
<?php
namespace App\Services;
use HITL\Client;
use Illuminate\Support\Facades\Log;
class ContentModerationService
{
private Client $client;
private string $moderationLoopId;
public function __construct()
{
$this->client = new Client([
'api_key' => config('hitl.api_key'),
'base_url' => config('hitl.base_url')
]);
$this->moderationLoopId = config('hitl.moderation_loop_id');
}
public function moderateContent(string $content, string $userId): string
{
$request = $this->client->requests()->create([
'loop_id' => $this->moderationLoopId,
'request_text' => "Review content from user {$userId}:\n\n{$content}",
'response_type' => 'single_select',
'response_config' => [
'options' => ['Approve', 'Remove', 'Warn User', 'Suspend User']
],
'priority' => 'high',
'metadata' => [
'user_id' => $userId,
'content_type' => 'comment'
]
]);
Log::info("Created moderation request: {$request['id']}");
// Return request ID for async processing
return $request['id'];
}
public function handleWebhook(array $payload): void
{
if ($payload['event'] === 'request.completed') {
$request = $payload['data']['request'];
$decision = $request['response_data'];
Log::info("Moderation completed for request {$request['id']}: {$decision}");
// Process the moderation decision
$this->processDecision($request, $decision);
}
}
private function processDecision(array $request, string $decision): void
{
$metadata = $request['metadata'];
$userId = $metadata['user_id'];
switch ($decision) {
case 'Remove':
// Delete the content
Log::info("Removing content for user {$userId}");
break;
case 'Warn User':
// Send warning to user
Log::info("Sending warning to user {$userId}");
break;
case 'Suspend User':
// Suspend the user account
Log::info("Suspending user {$userId}");
break;
default:
// Content approved, no action needed
Log::info("Content approved for user {$userId}");
}
}
}
// app/Http/Controllers/WebhookController.php
<?php
namespace App\Http\Controllers;
use App\Services\ContentModerationService;
use HITL\WebhookHandler;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class WebhookController extends Controller
{
private ContentModerationService $moderationService;
private WebhookHandler $webhookHandler;
public function __construct(ContentModerationService $moderationService)
{
$this->moderationService = $moderationService;
$this->webhookHandler = new WebhookHandler([
'secret' => config('hitl.webhook_secret')
]);
}
public function handle(Request $request): Response
{
try {
$payload = $this->webhookHandler->parseEvent(
$request->getContent(),
$request->headers->all()
);
$this->moderationService->handleWebhook($payload);
return response()->json(['status' => 'success']);
} catch (\Exception $e) {
return response()->json(['error' => $e->getMessage()], 400);
}
}
}
SDK Comparison
| Feature | Python | Node.js | Go | PHP |
|---|---|---|---|---|
| Async Support | ✅ Full | ✅ Native | ✅ Context | ❌ Sync only |
| Type Safety | ✅ Typed | ✅ TypeScript | ✅ Strong | ⚠️ Partial |
| Webhooks | ✅ Built-in | ✅ Built-in | ✅ Built-in | ✅ Built-in |
| Retry Logic | ✅ Configurable | ✅ Configurable | ✅ Configurable | ✅ Basic |
| Rate Limiting | ✅ Auto-handle | ✅ Auto-handle | ✅ Auto-handle | ✅ Auto-handle |
| Batch Ops | ✅ Available | ✅ Available | ✅ Manual | ✅ Manual |