RaidzATTENTION, WITH PROOF.

HTTP API reference

The Fastify API listens on port 4000 by default. In production the Next.js application proxies /api/v1/* to the private API service. JSON is used for request and response bodies.

Conventions

  • Validation failures return 400 with an error code; some endpoints include Zod details.
  • Unconfigured or unavailable identity dependencies return 503.
  • Identity endpoints use the raidz_session cookie. If a valid session does not exist, the API creates a user/profile/session and sends an HttpOnly, SameSite=Lax cookie, Secure in production, with a 30-day maximum age.
  • Challenge IDs are UUIDs and expire after five minutes.
  • Current CORS configuration does not grant cross-origin browser access.

Health

GET /health

Liveness only. Does not check PostgreSQL.

{ "status": "ok" }

GET /ready

Runs dependency checks, currently PostgreSQL by default. Returns 200 {"status":"ready"} or 503 {"status":"not_ready"}. Both health endpoints set Cache-Control: no-store.

Score

POST /v1/score/preview

Calculates Raidz Score V0 without persistence. Supply eleven numeric signals, completedCampaigns, and evidence for every component.

{
  "accountMaturity": 80,
  "audienceQuality": 75,
  "realReach": 70,
  "contentQuality": 85,
  "topicRelevance": 90,
  "socialScale": 60,
  "campaignPerformance": 0,
  "conversionPerformance": 0,
  "reliability": 0,
  "marketplaceRatings": 0,
  "verificationSignals": 0,
  "completedCampaigns": 0,
  "evidence": {
    "accountMaturity": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0.9, "explanationReason": "Account age and continuity" },
    "audienceQuality": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0.7, "explanationReason": "Sampled audience quality" },
    "realReach": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0.7, "explanationReason": "Recent median reach" },
    "contentQuality": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0.7, "explanationReason": "Original content review" },
    "topicRelevance": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0.8, "explanationReason": "Web3 topic fit" },
    "socialScale": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0.9, "explanationReason": "Normalized scale" },
    "campaignPerformance": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0, "explanationReason": "No completed Raidz campaign" },
    "conversionPerformance": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0, "explanationReason": "No consented outcome history" },
    "reliability": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0, "explanationReason": "No platform history" },
    "marketplaceRatings": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0, "explanationReason": "No platform ratings" },
    "verificationSignals": { "sourceTimestamp": "2026-09-03T00:00:00.000Z", "confidence": 0, "explanationReason": "No additional verification" }
  }
}

The response contains score, tier, performanceShare, all normalized components plus evidence, and version. Numeric signals are clamped to 0–100; evidence confidence is validated within 0–1.

Campaign policy

POST /v1/campaigns/preflight

{
  "channel": "x",
  "jurisdiction": "US",
  "category": "web3 product",
  "text": "Publish one original, clearly disclosed product review.",
  "compensated": true
}

Channels are x, telegram, web, onchain, or event. The response is ELIGIBLE or BLOCKED, a unique list of reason codes, and the policy version.

Missions

GET /v1/missions

Currently returns an empty live dataset:

{
  "data": [],
  "source": "database",
  "live": false,
  "notice": "No funded campaigns are represented by fixtures."
}

Profile and providers

GET /v1/profile

Returns the current profile and provider availability. x and telegram are true only when their necessary runtime configuration exists; wallet linking is available. Telegram bot ID and username may be returned as public configuration.

PATCH /v1/profile

All fields are optional: displayName, bio, locale, jurisdiction, languages, regions, narratives, availability, and profileVisibility. Collection sizes and string lengths are bounded by the route schema.

Wallet ownership

POST /v1/auth/wallet/challenge

{ "address": "0x1111111111111111111111111111111111111111", "chainId": 4663 }

Returns challengeId, the exact message to sign, expiry, and chain ID. Any other chain returns WRONG_CHAIN.

POST /v1/auth/wallet/verify

{
  "challengeId": "00000000-0000-4000-8000-000000000000",
  "address": "0x1111111111111111111111111111111111111111",
  "signature": "0x..."
}

The server checks the address against the challenge, verifies the EVM personal-message signature, atomically consumes the challenge, and links the checksummed address. Errors distinguish invalid input, expired/used challenge, wrong wallet, invalid signature, and replay.

X OAuth

GET /v1/auth/x/start

Creates a PKCE challenge and returns { "url": "https://x.com/i/oauth2/authorize?..." }. The browser must navigate to the returned URL.

GET /v1/auth/x/callback

X redirects here with code and compound state. The API validates session/state/PKCE, exchanges the code, reads the current profile, consumes the challenge, encrypts the token response, and redirects to the profile view with a success or error query.

Telegram Login

POST /v1/auth/telegram/verify

Accepts the Telegram Login payload fields id, auth_date, hash, and optional name, username, and photo URL. The signature and five-minute age are verified before the subject is pseudonymized and linked.

Disconnect

DELETE /v1/auth/:provider

provider is x, telegram, or wallet. Social links are deleted; active wallet links are marked revoked. Returns the updated profile.

Not yet exposed

There are no public endpoints yet for persistent campaign CRUD, claims, deliverables, verifier decisions, settlement, service bookings, reviews, analytics intake, Pons state, or admin operations.