REST API endpoints provided by PULO.
http://localhost:4311 # Local development
https://api.your-domain.com # Production
Demo mode uses cookie-based authentication:
- Admin: Session cookie from
/admin/login - FID 1 is admin in demo mode
Production mode requires real Far caster OAuth.
Basic health check.
Response:
{ "status": "ok", "timestamp": "2026-05-08T..." }Deep health check with component status.
Response:
{
"status": "ok",
"timestamp": "2026-05-08T...",
"uptime": 3600,
"checks": [
{ "component": "api", "status": "ok", "latencyMs": 1 },
{ "component": "database", "status": "ok", "latencyMs": 5 },
{ "component": "redis", "status": "ok", "latencyMs": 2 },
{ "component": "farcaster", "status": "ok", "details": { "rateLimitRemaining": 145 } },
{ "component": "llm", "status": "ok", "details": { "quotaRemaining": 8500 } },
{ "component": "queue", "status": "ok", "details": { "pendingJobs": 0, "runningJobs": 0 } },
{ "component": "system", "status": "ok", "details": { "memoryUsedMb": 67 } }
],
"metrics": { ... }
}Recent audit events (admin only).
Query Parameters:
limit— Max events to return (default: 100)
Response:
{
"events": [ ... ],
"total": 42
}Prometheus-compatible metrics endpoint.
Query Parameters:
format—prometheus(default) orjson
Response (Prometheus format):
# TYPE pulo_http_requests_total counter
pulo_http_requests_total{method="GET",path="/health",status="200"} 42
# TYPE pulo_uptime_seconds gauge
pulo_uptime_seconds 3600
Create an alert.
Request:
{
"type": "keyword" | "fid" | "cast_hash" | "truth_verdict",
"params": {
"keyword"?: "ethereum",
"fid"?: 12345,
"castHash"?: "abc123",
"verdict"?: "FALSE"
},
"delivery": {
"channel": "cast" | "mini_app"
}
}Response:
{
"id": "alert_123",
"created": true
}List user's alerts.
Response:
{
"alerts": [
{
"id": "alert_123",
"type": "keyword",
"params": { "keyword": "ethereum" },
"createdAt": "2026-05-08T..."
}
],
"total": 1
}Delete an alert.
Response:
{ "deleted": true }Get current usage statistics.
Response:
{
"plan": "free",
"truthChecks": { "used": 5, "limit": 10 },
"alerts": { "used": 3, "limit": 10 }
}Change subscription plan (admin override only).
Request:
{
"fid": 12345,
"plan": "pro"
}List all errors.
Query Parameters:
code— Filter by error codecategory— Filter by categorylimit— Max results (default: 100)
Response:
{
"errors": [
{
"id": "err_abc123",
"code": "VALIDATION_FAILED",
"message": "Invalid FID format",
"category": "validation",
"count": 3,
"firstSeen": "2026-05-08T...",
"lastSeen": "2026-05-08T..."
}
],
"total": 1
}Retry a failed error (admin only).
Response:
{
"success": true,
"jobId": "job_xyz"
}List all jobs.
Query Parameters:
status— Filter by statustype— Filter by job typelimit— Max results
Response:
{
"jobs": [
{
"id": "job_123",
"type": "truth_check",
"status": "completed",
"createdAt": "2026-05-08T...",
"completedAt": "2026-05-08T..."
}
],
"total": 1
}Cancel a job (admin only).
Response:
{ "cancelled": true }Retry a failed job (admin only).
Response:
{
"success": true,
"jobId": "job_456"
}List dead letter queue.
Response:
{
"jobs": [
{
"id": "dlq_789",
"originalJobId": "job_123",
"type": "truth_check",
"error": "LLM_TIMEOUT",
"attempts": 3,
"failedAt": "2026-05-08T..."
}
],
"total": 1
}Retry from dead letter (admin only).
Response:
{
"success": true,
"jobId": "job_789"
}Neynar webhook endpoint.
Headers:
x-neynar-signature— HMAC signaturex-webhook-timestamp— Unix timestamp
Body:
{
"type": "mention.created",
"data": {
"cast": {
"hash": "abc123",
"author": { "fid": 12345 },
"text": "@pulo is this real?"
}
}
}Response:
{
"received": true,
"verified": true,
"eventId": "evt_xyz"
}Test webhook endpoint (no signature required).
Body:
{
"type": "mention",
"fid": 123,
"text": "test mention"
}Seed demo data (admin only).
Response:
{
"success": true,
"scenarios": 6
}Run demo scenarios (admin only).
Response:
{
"success": true,
"results": [...]
}Reset demo data (admin only).
Response:
{
"success": true
}All endpoints may return:
{ "error": "VALIDATION_FAILED", "message": "Invalid input" }{ "error": "UNAUTHORIZED", "message": "Authentication required" }{ "error": "FORBIDDEN", "message": "Admin access required" }{ "error": "NOT_FOUND", "message": "Resource not found" }{ "error": "RATE_LIMITED", "message": "Rate limit exceeded", "retryAfter": 60 }{ "error": "INTERNAL_ERROR", "message": "An unexpected error occurred" }- Global: 120 requests per minute per IP
- User-specific limits depend on plan
Configure allowed origins via ALLOWED_ORIGINS environment variable.
ALLOWED_ORIGINS=https://your-domain.com,https://app.warpcast.com