← Back to Docs
Code Examples
Complete working examples for Agent Passport authentication in Python, TypeScript, and Rust.
🐍
Python
Installation
bash
pip install pynacl base58 requests
Complete Agent Auth Client
python
"""NervePay Agent Passport Authentication ClientComplete example for authenticating API requests with Ed25519 signatures."""import nacl.signingimport base64import base58import timeimport uuidimport requestsfrom typing import Optional, Dict, Anyclass AgentPassport:"""Client for authenticating API requests using Agent Passport."""def __init__(self, agent_did: str, private_key_base58: str, base_url: str = "https://api.nervepay.xyz"):"""Initialize the Agent Passport client.Args:agent_did: Your agent's DID (e.g., "did:nervepay:agent:7xKp...")private_key_base58: Base58-encoded Ed25519 private key (64 bytes)base_url: NervePay API base URL"""self.agent_did = agent_didself.base_url = base_url# Decode the base58 private keykey_bytes = base58.b58decode(private_key_base58)# Use first 32 bytes as seed to create signing keyself.signing_key = nacl.signing.SigningKey(key_bytes[:32])def _create_signature(self, method: str, path: str, nonce: str, timestamp: str) -> str:"""Create Ed25519 signature for the request."""# Canonical payload formatpayload = f"{method}\n{path}\n{nonce}\n{timestamp}\n{self.agent_did}"# Sign the payloadsigned = self.signing_key.sign(payload.encode())signature_b64 = base64.b64encode(signed.signature).decode()return f"ed25519:{signature_b64}"def get_auth_headers(self, method: str, path: str) -> Dict[str, str]:"""Generate authentication headers for a request.Args:method: HTTP method (GET, POST, etc.)path: Request path (e.g., "/api/data")Returns:Dictionary of authentication headers"""nonce = str(uuid.uuid4())timestamp = str(int(time.time()))signature = self._create_signature(method, path, nonce, timestamp)return {"Agent-DID": self.agent_did,"X-Agent-Signature": signature,"X-Agent-Nonce": nonce,"X-Signature-Timestamp": timestamp,}def request(self,method: str,url: str,headers: Optional[Dict[str, str]] = None,**kwargs) -> requests.Response:"""Make an authenticated request.Args:method: HTTP methodurl: Full URL or path (if path, base_url is prepended)headers: Additional headers to include**kwargs: Additional arguments passed to requestsReturns:Response object"""from urllib.parse import urlparse# Handle relative pathsif not url.startswith("http"):url = f"{self.base_url}{url}"path = urlparse(url).path# Merge auth headers with any provided headersall_headers = self.get_auth_headers(method, path)if headers:all_headers.update(headers)return requests.request(method, url, headers=all_headers, **kwargs)def get(self, url: str, **kwargs) -> requests.Response:"""Make authenticated GET request."""return self.request("GET", url, **kwargs)def post(self, url: str, **kwargs) -> requests.Response:"""Make authenticated POST request."""return self.request("POST", url, **kwargs)def whoami(self) -> Dict[str, Any]:"""Get current agent identity information."""response = self.get("/v1/agent-identity/whoami")response.raise_for_status()return response.json()def get_capabilities(self) -> Dict[str, Any]:"""Get agent capabilities and limits."""response = self.get("/v1/agent-identity/capabilities")response.raise_for_status()return response.json()# Usage Exampleif __name__ == "__main__":# Initialize with your credentialsagent = AgentPassport(agent_did="did:nervepay:agent:7xKpQm3...",private_key_base58="your-private-key-base58")# Check identityidentity = agent.whoami()print(f"Agent: {identity['name']}")print(f"DID: {identity['did']}")print(f"Reputation: {identity['reputation_score']}")# Make authenticated API callsresponse = agent.get("https://api.example.com/protected-resource")print(response.json())
📘
TypeScript
Installation
bash
npm install tweetnacl bs58 uuid
Complete Agent Auth Client
typescript
/*** NervePay Agent Passport Authentication Client* Complete example for authenticating API requests with Ed25519 signatures.*/import nacl from 'tweetnacl';import bs58 from 'bs58';import { v4 as uuidv4 } from 'uuid';interface AuthHeaders {'Agent-DID': string;'X-Agent-Signature': string;'X-Agent-Nonce': string;'X-Signature-Timestamp': string;}interface AgentIdentity {did: string;name: string;reputation_score: number;public_key: string;capabilities: Record<string, unknown>;}export class AgentPassport {private agentDid: string;private signingKey: Uint8Array;private baseUrl: string;/*** Initialize the Agent Passport client.* @param agentDid - Your agent's DID (e.g., "did:nervepay:agent:7xKp...")* @param privateKeyBase58 - Base58-encoded Ed25519 private key (64 bytes)* @param baseUrl - NervePay API base URL*/constructor(agentDid: string,privateKeyBase58: string,baseUrl: string = 'https://api.nervepay.xyz') {this.agentDid = agentDid;this.baseUrl = baseUrl;// Decode base58 private key (64 bytes: 32 seed + 32 public)const keyBytes = bs58.decode(privateKeyBase58);this.signingKey = keyBytes;}private createSignature(method: string, path: string, nonce: string, timestamp: string): string {// Canonical payload formatconst payload = `${method}\n${path}\n${nonce}\n${timestamp}\n${this.agentDid}`;// Sign the payloadconst message = new TextEncoder().encode(payload);const signature = nacl.sign.detached(message, this.signingKey);const signatureB64 = Buffer.from(signature).toString('base64');return `ed25519:${signatureB64}`;}/*** Generate authentication headers for a request.*/getAuthHeaders(method: string, path: string): AuthHeaders {const nonce = uuidv4();const timestamp = Math.floor(Date.now() / 1000).toString();const signature = this.createSignature(method, path, nonce, timestamp);return {'Agent-DID': this.agentDid,'X-Agent-Signature': signature,'X-Agent-Nonce': nonce,'X-Signature-Timestamp': timestamp,};}/*** Make an authenticated fetch request.*/async fetch(url: string, options: RequestInit = {}): Promise<Response> {// Handle relative pathsconst fullUrl = url.startsWith('http') ? url : `${this.baseUrl}${url}`;const urlObj = new URL(fullUrl);const method = options.method || 'GET';const authHeaders = this.getAuthHeaders(method, urlObj.pathname);return fetch(fullUrl, {...options,headers: {...options.headers,...authHeaders,},});}/*** Get current agent identity information.*/async whoami(): Promise<AgentIdentity> {const response = await this.fetch('/v1/agent-identity/whoami');if (!response.ok) {throw new Error(`Failed to get identity: ${response.status}`);}return response.json();}/*** Get agent capabilities and limits.*/async getCapabilities(): Promise<Record<string, unknown>> {const response = await this.fetch('/v1/agent-identity/capabilities');if (!response.ok) {throw new Error(`Failed to get capabilities: ${response.status}`);}return response.json();}}// Usage Exampleasync function main() {const agent = new AgentPassport('did:nervepay:agent:7xKpQm3...','your-private-key-base58');// Check identityconst identity = await agent.whoami();console.log(`Agent: ${identity.name}`);console.log(`DID: ${identity.did}`);console.log(`Reputation: ${identity.reputation_score}`);// Make authenticated API callsconst response = await agent.fetch('https://api.example.com/protected-resource');const data = await response.json();console.log(data);}main().catch(console.error);
🦀
Rust
Cargo.toml
toml
[dependencies]ed25519-dalek = "2.0"bs58 = "0.5"base64 = "0.21"uuid = { version = "1.0", features = ["v4"] }reqwest = { version = "0.11", features = ["json"] }tokio = { version = "1.0", features = ["full"] }serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"
Complete Agent Auth Client
rust
//! NervePay Agent Passport Authentication Client//! Complete example for authenticating API requests with Ed25519 signatures.use ed25519_dalek::{Signature, Signer, SigningKey};use reqwest::header::{HeaderMap, HeaderValue};use serde::{Deserialize, Serialize};use std::time::{SystemTime, UNIX_EPOCH};use uuid::Uuid;#[derive(Debug, Deserialize)]pub struct AgentIdentity {pub did: String,pub name: String,pub reputation_score: f64,pub public_key: String,}pub struct AgentPassport {agent_did: String,signing_key: SigningKey,base_url: String,client: reqwest::Client,}impl AgentPassport {/// Create a new Agent Passport client.pub fn new(agent_did: &str, private_key_base58: &str, base_url: Option<&str>) -> Self {// Decode base58 private keylet key_bytes = bs58::decode(private_key_base58).into_vec().expect("Invalid base58 key");// Use first 32 bytes as seedlet seed: [u8; 32] = key_bytes[..32].try_into().expect("Key too short");let signing_key = SigningKey::from_bytes(&seed);Self {agent_did: agent_did.to_string(),signing_key,base_url: base_url.unwrap_or("https://api.nervepay.xyz").to_string(),client: reqwest::Client::new(),}}/// Create Ed25519 signature for the request.fn create_signature(&self, method: &str, path: &str, nonce: &str, timestamp: &str) -> String {let payload = format!("{}\n{}\n{}\n{}\n{}",method, path, nonce, timestamp, self.agent_did);let signature: Signature = self.signing_key.sign(payload.as_bytes());let signature_b64 = base64::encode(signature.to_bytes());format!("ed25519:{}", signature_b64)}/// Generate authentication headers for a request.pub fn get_auth_headers(&self, method: &str, path: &str) -> HeaderMap {let nonce = Uuid::new_v4().to_string();let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs().to_string();let signature = self.create_signature(method, path, &nonce, ×tamp);let mut headers = HeaderMap::new();headers.insert("Agent-DID", HeaderValue::from_str(&self.agent_did).unwrap());headers.insert("X-Agent-Signature", HeaderValue::from_str(&signature).unwrap());headers.insert("X-Agent-Nonce", HeaderValue::from_str(&nonce).unwrap());headers.insert("X-Signature-Timestamp", HeaderValue::from_str(×tamp).unwrap());headers}/// Make an authenticated GET request.pub async fn get(&self, path: &str) -> reqwest::Result<reqwest::Response> {let url = format!("{}{}", self.base_url, path);let headers = self.get_auth_headers("GET", path);self.client.get(&url).headers(headers).send().await}/// Make an authenticated POST request.pub async fn post<T: Serialize>(&self, path: &str, body: &T) -> reqwest::Result<reqwest::Response> {let url = format!("{}{}", self.base_url, path);let headers = self.get_auth_headers("POST", path);self.client.post(&url).headers(headers).json(body).send().await}/// Get current agent identity information.pub async fn whoami(&self) -> reqwest::Result<AgentIdentity> {self.get("/v1/agent-identity/whoami").await?.json().await}}#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> {let agent = AgentPassport::new("did:nervepay:agent:7xKpQm3...","your-private-key-base58",None,);// Check identitylet identity = agent.whoami().await?;println!("Agent: {}", identity.name);println!("DID: {}", identity.did);println!("Reputation: {}", identity.reputation_score);Ok(())}
💻
cURL
For quick testing, you can manually construct authenticated requests using cURL. Note: You'll need to generate the signature separately using a script.
Example Request
bash
# Set your credentialsexport AGENT_DID="did:nervepay:agent:7xKpQm3..."export NONCE=$(uuidgen | tr '[:upper:]' '[:lower:]')export TIMESTAMP=$(date +%s)# Generate signature (you need to compute this with your private key)# See Python/TypeScript examples for signature generationexport SIGNATURE="ed25519:YOUR_SIGNATURE_HERE"# Make authenticated requestcurl -X GET "https://api.nervepay.xyz/v1/agent-identity/whoami" \-H "Agent-DID: $AGENT_DID" \-H "X-Agent-Signature: $SIGNATURE" \-H "X-Agent-Nonce: $NONCE" \-H "X-Signature-Timestamp: $TIMESTAMP"
Response Example
json
{"did": "did:nervepay:agent:7xKpQm3...","name": "My AI Agent","reputation_score": 85.5,"public_key": "ed25519:abc123...","capabilities": {"max_transaction_amount": 100.00,"allowed_operations": ["read", "write"]},"created_at": "2024-01-15T10:30:00Z"}
Use Case Examples
Agent-to-Agent Authentication
Agents can authenticate with each other in multi-agent systems using their passports.
Learn moreAPI Protection
Verify agent identity before granting access to protected resources. Full server-side verification example included.
View codeSign in with NerveSoon
OAuth-like flow for agents to authenticate with third-party services. Includes UI and headless flows.
Integration guideEnterprise Governance
Audit all agent actions, enforce transaction limits, and meet compliance requirements.
Overview