# ASP.NET Core agent verification

Example controller that verifies agents by wallet (Path 1) or by JWS/JWT (Path 2). The real API uses `IsDelegateAttestationVerifier` (with `IsDelegateVerifierConfig` and `IsDelegateVerifierOptions`) and `AttestedMerkleExchangeReader` with a verification context. See the [ProofPack .NET README](https://github.com/zipwireapp/ProofPack/blob/main/dotnet/README.md) and [EXAMPLES.md](https://github.com/zipwireapp/ProofPack/blob/main/dotnet/EXAMPLES.md) for config and setup.

```csharp
using Microsoft.AspNetCore.Mvc;
using Zipwire.ProofPack;
using Zipwire.ProofPack.Ethereum;

[ApiController]
[Route("api")]
public class AgentController : ControllerBase
{
    private readonly IsDelegateAttestationVerifier _delegateVerifier;
    private readonly AttestedMerkleExchangeReader _reader;

    public AgentController(IsDelegateAttestationVerifier delegateVerifier, AttestedMerkleExchangeReader reader)
    {
        _delegateVerifier = delegateVerifier;
        _reader = reader;
    }

    [HttpPost("time-tracking/log")]
    public async Task<IActionResult> LogTime([FromHeader] string xAgentWallet)
    {
        // Verify agent is authorized
        var isAuthorized = await _delegateVerifier.VerifyByWalletAsync(xAgentWallet);

        if (!isAuthorized)
        {
            return Forbid("Agent not authorized by verified human");
        }

        // Process time entry
        return Ok(new { message = "Time logged successfully" });
    }

    [HttpPost("payments/claim")]
    public async Task<IActionResult> ClaimPayment([FromHeader] string authorization)
    {
        if (!authorization?.StartsWith("Bearer ") == true)
        {
            return BadRequest("JWS or JWT required for payment claims");
        }

        var jws = authorization.Substring(7);
        var result = await _reader.ReadAsync(jws, verificationContext);

        if (!result.IsValid)
        {
            return Forbid("Invalid authorization proof");
        }

        var claims = result.Document.MerkleTree.Leaves;

        // Verify claims meet payment requirements
        if (!claims.ContainsKey("verifiedHuman") || !bool.TryParse(claims["verifiedHuman"], out var isHuman) || !isHuman)
        {
            return Forbid("Payment requires human verification");
        }

        // Process payment claim
        return Ok(new { message = "Payment processed", agentWallet = result.AgentWallet });
    }
}
```

Full guide: [ProofPack & Agent Delegation](https://docs.zipwire.io/tools-and-integrations/proofpack-agent-delegation).
