Go
A hand-rolled Go client for the FedShield REST API. Uses stdlib net/http and encoding/json — no external dependencies. An official SDK is on the roadmap.
Complete example
Section titled “Complete example”The whole integration in under 100 lines:
package main
import ( "bytes" "context" "encoding/json" "fmt" "log" "net/http" "os" "time"
"github.com/google/uuid")
const apiBase = "https://api.fedshield.io"
type Client struct { http *http.Client apiKey string}
func NewClient(apiKey string) *Client { return &Client{ http: &http.Client{Timeout: 5 * time.Second}, apiKey: apiKey, }}
type TrustEvent struct { SchemaVersion string `json:"schema_version"` EventID string `json:"event_id"` EventType string `json:"event_type"` PeerID string `json:"peer_id"` PlayerID string `json:"player_id"` GameID string `json:"game_id"` Severity float64 `json:"severity"` Timestamp time.Time `json:"timestamp"`}
type TrustScore struct { PlayerID string `json:"player_id"` Score float64 `json:"score"` Confidence float64 `json:"confidence"` Verdict string `json:"verdict"` EventCount int `json:"event_count"`}
func (c *Client) SubmitEvent(ctx context.Context, e TrustEvent) error { body, _ := json.Marshal(e) req, _ := http.NewRequestWithContext(ctx, "POST", apiBase+"/api/v1/events", bytes.NewReader(body)) req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Peer-API-Key", c.apiKey) resp, err := c.http.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 300 { return fmt.Errorf("submit event: %s", resp.Status) } return nil}
func (c *Client) GetTrustScore(ctx context.Context, playerID string) (*TrustScore, error) { req, _ := http.NewRequestWithContext(ctx, "GET", apiBase+"/api/v1/players/"+playerID+"/trust-score", nil) resp, err := c.http.Do(req) if err != nil { return nil, err } defer resp.Body.Close() var s TrustScore if err := json.NewDecoder(resp.Body).Decode(&s); err != nil { return nil, err } return &s, nil}
func main() { ctx := context.Background()
// Read your peer_id and api_key from your secrets store. // Register your peer once via the dashboard at https://fedshield.io/app/peers. client := NewClient(os.Getenv("FEDSHIELD_API_KEY")) peerID := os.Getenv("FEDSHIELD_PEER_ID")
event := TrustEvent{ SchemaVersion: "1.0.0", EventID: uuid.NewString(), EventType: "report_cheating", PeerID: peerID, PlayerID: "player-alice-123", GameID: "my-game", Severity: 0.85, Timestamp: time.Now().UTC(), } if err := client.SubmitEvent(ctx, event); err != nil { log.Fatalf("submit: %v", err) }
score, err := client.GetTrustScore(ctx, "player-alice-123") if err != nil { log.Fatalf("score: %v", err) } fmt.Printf("player score=%.1f verdict=%s confidence=%.2f\n", score.Score, score.Verdict, score.Confidence)}Apply enforcement policy
Section titled “Apply enforcement policy”The score is advisory. Your game decides what to do:
func decideMatchmakingPolicy(score *TrustScore) string { if score.Confidence < 0.2 { // Not enough history — treat as neutral. return "ranked_allowed" } switch score.Verdict { case "trusted", "neutral": return "ranked_allowed" case "suspicious": return "ranked_locked_24h" case "untrusted": return "ranked_locked_permanent" default: return "ranked_allowed" }}The nine event types
Section titled “The nine event types”Set event_type on the TrustEvent struct to one of:
| Event type | When to submit |
|---|---|
report_cheating | Player caught cheating (aimbot, wallhack, macro) |
report_toxicity | Chat / voice reported for abuse |
report_spam | Repeated no-value events (queue-dodging, AFK farming) |
friendly_fire | Team-killing above the tolerance floor |
session_anomaly | Impossible movement, teleport, physics violations |
matchmaking_fraud | Boosting, smurfing, ranked manipulation |
ban_applied | Your studio issued a ban (severity 1.0) |
ban_lifted | Your studio reversed a ban |
commendation | Positive signal — good sportsmanship, teaching new players |
Persisting credentials
Section titled “Persisting credentials”Register your peer once via the dashboard at https://fedshield.io/app/peers, copy the peer_id and api_key into your secrets store, then read them from env vars as in the example above.