Skip to content

Start typing to search the documentation.

Verifying Agents (Service Operator)

This guide shows how to add Self Agent ID verification to your API. After setup, only registered, human-backed agents can access your protected endpoints.

1. Install the SDK

npm install @selfxyz/agent-sdk    # TypeScript
pip install selfxyz-agent-sdk      # Python
cargo add self-agent-sdk           # Rust

2. Create a Verifier

Use the builder pattern to configure verification policy:

import { SelfAgentVerifier } from "@selfxyz/agent-sdk";

const verifier = SelfAgentVerifier.create()
  .network("mainnet")
  .requireAge(18)
  .requireOFAC()
  .requireSelfProvider()   // Ensure Self Protocol proofs (default: true)
  .sybilLimit(3)           // Max 3 agents per human
  .rateLimit({ perMinute: 10 })
  .build();

Builder Options

MethodDescriptionDefault
.network(name)"mainnet" or "testnet""testnet"
.requireAge(n)Minimum age (18 or 21)None
.requireOFAC()OFAC sanctions screeningOff
.requireNationality(...codes)Allowed ISO country codesAny
.requireSelfProvider()Require Self Protocol proofstrue
.sybilLimit(n)Max agents per human (0 = unlimited)1
.rateLimit(config)Per-agent rate limitingNone
.replayProtection(enabled?)Signature replay detectiontrue
.includeCredentials()Attach credentials to requestfalse
.maxAge(ms)Max signature age300000 (5 min)
.cacheTtl(ms)On-chain query cache60000 (1 min)

3. Add Middleware

import express from "express";

const app = express();
app.use(express.json());

// Protect all /api routes
app.use("/api", verifier.auth());

app.post("/api/data", (req, res) => {
  // req.agent is populated after verification
  console.log("Agent:", req.agent.address);
  console.log("Agent ID:", req.agent.agentId);
  console.log("Credentials:", req.agent.credentials);
  res.json({ ok: true });
});

4. Request Shape After Verification

After successful verification, req.agent (or equivalent) contains:

FieldTypeDescription
addressstringAgent’s Ethereum address
agentIdnumberOn-chain NFT token ID
agentKeystringDerived bytes32 key
isVerifiedbooleanOn-chain verification status
proofProviderstringProvider contract address
credentialsobjectZK-attested credentials (if includeCredentials())

5. Credential-Based Access Control

Use credentials to gate by age, OFAC status, or nationality:

const verifier = SelfAgentVerifier.create()
  .requireAge(21)                          // Must be 21+
  .requireOFAC()                           // Must pass OFAC screening
  .requireNationality("US", "GB", "DE")    // Only these countries
  .includeCredentials()                    // Attach credentials to request
  .build();

app.post("/api/restricted", verifier.auth(), (req, res) => {
  const { nationality, olderThan, ofac } = req.agent.credentials;
  // nationality: "US", olderThan: 21, ofac: [true, true, true]
});

6. Sybil Resistance

Control how many agents one human can use against your API:

SettingBehavior
.sybilLimit(1)Strict — one agent per human (default)
.sybilLimit(5)Moderate — up to 5 agents per human
.sybilLimit(0)Detection only — unlimited, but sameHuman() available

The verifier checks getAgentCountForHuman(nullifier) on-chain.

7. Provider Verification

The verifier checks that getProofProvider(agentId) matches Self Protocol’s provider address.

8. Replay Protection + Rate Limiting

Replay protection (enabled by default):

  • Caches {signature + timestamp} hashes (10,000 entries)
  • Same signature cannot be used twice

Rate limiting (optional):

.rateLimit({ perMinute: 10, perHour: 100 })

Per-agent sliding-window rate limits.

9. Error Handling

The middleware returns standard HTTP errors:

StatusMeaning
401Missing or invalid signature headers
403Agent not verified, failed policy check, or rate limited
500On-chain query failed

Handle these in your client:

const res = await agent.fetch("https://api.example.com/data", { method: "POST" });
if (res.status === 403) {
  const error = await res.json();
  // { error: "Agent not verified on-chain" }
  // { error: "Age requirement not met: requires 18, has 0" }
  // { error: "Rate limit exceeded" }
}

Next Steps