AbuseGraphDocs
Guides

AbuseGraph + Go

Go net/http client POSTs to /api/v1/check with sk_ and x-abusegraph-site on register and login.

Quick path

  1. Set ABUSEGRAPH_SECRET_KEY and ABUSEGRAPH_SITE in env.
  2. POST JSON to https://abusegraph.com/api/v1/check before creating a session.
  3. Map verdict to 403 (block) or step-up (challenge).

Keys

KeyEnvUse
SecretABUSEGRAPH_SECRET_KEY (sk_test_… / sk_live_…)Server /api/v1/check
PublishableNEXT_PUBLIC_ABUSEGRAPH_PUBLISHABLE_KEY (pk_test_…)Browser SDK
SiteABUSEGRAPH_SITEDNS-verified domain

Free includes 1,000 live API checks / month after DNS verify. Test keys never bill.

Env

ABUSEGRAPH_SITE=yourdomain.com
ABUSEGRAPH_CHECK_URL=https://abusegraph.com/api/v1/check
ABUSEGRAPH_SECRET_KEY=sk_test_…

Use sk_live_… in production after DNS verify.

Server check

Go uses direct HTTP POST to https://abusegraph.com/api/v1/check. Events: signup | login | password_reset | email_change. Optional sessionId.

package abusegraph

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
)

type CheckRequest struct {
	Email     string `json:"email,omitempty"`
	UserID    string `json:"userId,omitempty"`
	Event     string `json:"event,omitempty"`
	SessionID string `json:"sessionId,omitempty"`
	Site      string `json:"site"`
}

type CheckResponse struct {
	Verdict string  `json:"verdict"`
	Score   float64 `json:"score"`
	Summary string  `json:"summary,omitempty"`
}

func Check(email, event string, extra map[string]any) (*CheckResponse, error) {
	site := os.Getenv("ABUSEGRAPH_SITE")
	checkURL := os.Getenv("ABUSEGRAPH_CHECK_URL")
	if checkURL == "" {
		checkURL = "https://abusegraph.com/api/v1/check"
	}

	body := map[string]any{
		"email": email,
		"event": event,
		"site":  site,
	}
	for k, v := range extra {
		body[k] = v
	}

	raw, _ := json.Marshal(body)
	req, err := http.NewRequest("POST", checkURL, bytes.NewReader(raw))
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("x-api-key", os.Getenv("ABUSEGRAPH_SECRET_KEY")) // sk_test_…
	req.Header.Set("x-abusegraph-site", site)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer res.Body.Close()

	if res.StatusCode == 402 {
		return nil, fmt.Errorf("credits_exhausted")
	}
	if res.StatusCode >= 400 {
		return nil, fmt.Errorf("check failed: %d", res.StatusCode)
	}

	var out CheckResponse
	return &out, json.NewDecoder(res.Body).Decode(&out)
}

Register handler:

result, err := abusegraph.Check(email, "signup", nil)
if err != nil { /* fail open or 503 */ }
if result.Verdict == "block" {
	http.Error(w, "signup blocked", http.StatusForbidden)
	return
}
// create user + session

If you serve a web UI, forward toCheckBody fields from @abusegraph/sdk in the request body — NEVER use browser-only checks as the authoritative decision.

Lifecycle events

  • loginCheck(email, "login", nil) before session issue.
  • password_resetevent: "password_reset" on reset request.
  • email_changeevent: "email_change" after email update.

Platform

Lists, rules, and linked accounts apply on every check — configure in the console. Optional session: POST /api/v1/session. Native apps: iOS, Android, React Native.

Verify

Register a test user with sk_test_…, confirm Activity shows the check, and blocked emails get 403.