Documentation Index Fetch the complete documentation index at: https://docs.voight.xyz/llms.txt
Use this file to discover all available pages before exploring further.
If you can’t or don’t want to add a dependency, Voight accepts raw HTTP POST from any runtime — curl, Python, Go, Rust, browsers, embedded devices, anything that speaks JSON over HTTPS.
Endpoint
POST https://voight-production.up.railway.app/v1/events
Authentication
Authorization: Bearer vk_YOUR_API_KEY
Content-Type: application/json
Generate your vk_ key at voight.xyz/dashboard/settings .
Minimal payload
curl https://voight-production.up.railway.app/v1/events \
-H "authorization: Bearer $VOIGHT_KEY " \
-H "content-type: application/json" \
-d '{
"agentId": "trading-bot.sol",
"type": "tx",
"toolExecuted": "jupiter.swap",
"transaction": "4zK...9Fp"
}'
Response:
{
"id" : "evt_clz3..." ,
"accepted" : true ,
"agentId" : "cmoq..." ,
"eventId" : "evt_clz3..."
}
The server returns the resolved agentId (a CUID) — store it locally if you want subsequent events to skip label resolution.
Full payload schema
{
"agentId" : "trading-bot.sol" ,
"timestamp" : "2026-05-12T14:02:54.084Z" ,
"type" : "tx" ,
"input" : { "prompt" : "..." , "context" : { } },
"reasoning" : "free-form trace" ,
"toolsConsidered" : [ "jupiter.swap" , "orca.swap" ],
"toolExecuted" : "jupiter.swap" ,
"transaction" : "4zK...9Fp" ,
"amount" : { "token" : "SOL" , "value" : 1.5 },
"outcome" : "success" ,
"durationMs" : 184 ,
"errorMessage" : "optional, when outcome=failed" ,
"model" : "claude-opus-4-7" ,
"metadata" : {
"source" : "my-trading-bot" ,
"strategy" : "mean-reversion" ,
"tokensBreakdown" : {
"inputBase" : 50 ,
"cacheCreation" : 100 ,
"cacheRead" : 850 ,
"output" : 200
},
"privacyLevel" : "standard"
}
}
All fields except agentId are optional. The server defaults type: 'decision' if omitted.
Privacy on the HTTP path
The HTTP path does not apply PII scrubbing — that’s a client-side operation that requires the SDK. If you’re calling HTTP directly, you’re responsible for scrubbing sensitive content before it leaves your machine.
To make Voight respect privacy controls on HTTP events, include metadata.privacyLevel: 'minimal' | 'standard' | 'full' so the dashboard can chip them correctly. The scrubbing itself is your responsibility.
For most use cases, the library mode SDK is the right call — import { scrubPii } from '@voightxyz/sdk' gives you the same scrubbing without adopting the hook handler.
Examples
Python
import requests
import os
def log_event ( payload ):
response = requests.post(
"https://voight-production.up.railway.app/v1/events" ,
headers = {
"authorization" : f "Bearer { os.environ[ 'VOIGHT_KEY' ] } " ,
"content-type" : "application/json" ,
},
json = payload,
timeout = 5 ,
)
response.raise_for_status()
return response.json()
log_event({
"agentId" : "py-bot" ,
"type" : "action" ,
"toolExecuted" : "fetch_market_data" ,
"outcome" : "success" ,
"durationMs" : 412 ,
})
package main
import (
" bytes "
" encoding/json "
" net/http "
" os "
)
func logEvent ( payload map [ string ] any ) error {
body , _ := json . Marshal ( payload )
req , _ := http . NewRequest ( "POST" ,
"https://voight-production.up.railway.app/v1/events" ,
bytes . NewBuffer ( body ))
req . Header . Set ( "Authorization" , "Bearer " + os . Getenv ( "VOIGHT_KEY" ))
req . Header . Set ( "Content-Type" , "application/json" )
resp , err := http . DefaultClient . Do ( req )
if err != nil {
return err
}
defer resp . Body . Close ()
return nil
}
Rust
use reqwest :: Client ;
use serde_json :: json;
async fn log_event ( payload : serde_json :: Value ) -> reqwest :: Result <()> {
let client = Client :: new ();
let api_key = std :: env :: var ( "VOIGHT_KEY" ) . unwrap ();
client . post ( "https://voight-production.up.railway.app/v1/events" )
. bearer_auth ( & api_key )
. json ( & payload )
. send ()
. await ?
. error_for_status () ? ;
Ok (())
}
Browser / fetch
await fetch ( 'https://voight-production.up.railway.app/v1/events' , {
method: 'POST' ,
headers: {
'authorization' : `Bearer ${ VOIGHT_KEY } ` ,
'content-type' : 'application/json' ,
},
body: JSON . stringify ({
agentId: 'browser-agent' ,
reasoning: 'user clicked the swap button' ,
}),
})
CORS is configured to allow https://voight.xyz and https://www.voight.xyz. For other origins, you’ll need server-side proxying.
Status codes
Code Meaning 202 AcceptedEvent received and persisted (returns { id, accepted: true, agentId }) 400 Bad RequestPayload failed Zod validation (response includes details) 401 UnauthorizedMissing or invalid API key 410 GoneThe agent has been soft-deleted, ingestion blocked 429 Too Many RequestsRate-limited (honor Retry-After header) 500 Server ErrorBackend issue — retry with exponential backoff
Rate limits
Per pricing tier:
Tier Events / month Free 10,000 Pro 300,000 Enterprise Unlimited
Quotas are advisory today, enforced server-side starting v1.0. Burst rate-limiting (per-second) is in place to prevent abuse.
Next
Library mode For JS/TS — gives you retry, error types, and PII scrubbing for free.
POST /v1/events reference Full schema definition with every field documented.