Clav
Webhooks

Event catalog

Every event a Clav webhook can receive and the fields each one carries.

Naming convention

Events follow the format <resource>.<past-tense fact>, such as wallet.verified. The resource comes first so you can handle a whole domain by prefix. The verb is in the past tense because the event announces something that already happened.

New events may be added without notice. Ignore the ones your endpoint does not recognize and respond 2xx anyway, so they do not trigger needless retries.

Available events

EventWhen it is sent
wallet.verifiedA wallet proof was accepted.
wallet.failedA wallet proof was rejected or arrived after the deadline.

Wallet events

Both wallet events share the same data shape. They are emitted by the wallet verification product.

FieldTypeDescription
organizationIdstringOrganization that owns the challenge.
challengeIdstringChallenge identifier.
externalCustomerIdstringThe customer identifier you sent when opening the challenge.
chainstringEVM, BITCOIN, TRON or SOLANA.
addressstringNormalized address that had to be proved.
methodstringSIGNATURE or MICRO_TRANSACTION.
noncestringUnique challenge identifier, the same as in GET /v1/wallet-proofs/{nonce}.
statusstringVERIFIED, FAILED or EXPIRED.
recoveredAddressstring or nullAddress that actually signed, when it could be recovered.
failureReasonstring or nullWhy it failed. null on wallet.verified.
verifiedAtstring or nullVerification time, in ISO-8601.
verifiedWalletIdstring or nullVerified wallet created or updated. null on wallet.failed.

wallet.verified

{
  "id": "65f0a1b2c3d4e5f60718293a-wallet.verified",
  "event": "wallet.verified",
  "occurredAt": "2026-09-16T12:04:11.000Z",
  "data": {
    "organizationId": "65e9f0a1b2c3d4e5f6071829",
    "challengeId": "65f0a1b2c3d4e5f60718293a",
    "externalCustomerId": "customer-8842",
    "chain": "EVM",
    "address": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
    "method": "SIGNATURE",
    "nonce": "a3f1c0d9e8b7a6f5e4d3c2b1a0998877665544332211ffeeddccbbaa99887766",
    "status": "VERIFIED",
    "recoveredAddress": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
    "failureReason": null,
    "verifiedAt": "2026-09-16T12:04:11.000Z",
    "verifiedWalletId": "65f0a1b2c3d4e5f60718293b"
  }
}

wallet.failed

Sent when the signature is rejected or arrives after the deadline. Check status to tell the two cases apart and failureReason for the cause. The list of reasons is on the wallet verification page. A challenge that lapses with no attempt at all sends no event.

{
  "id": "65f0a1b2c3d4e5f60718293a-wallet.failed",
  "event": "wallet.failed",
  "occurredAt": "2026-09-16T12:04:11.000Z",
  "data": {
    "organizationId": "65e9f0a1b2c3d4e5f6071829",
    "challengeId": "65f0a1b2c3d4e5f60718293a",
    "externalCustomerId": "customer-8842",
    "chain": "EVM",
    "address": "0x5b38da6a701c568545dcfcb03fcb875f56beddc4",
    "method": "SIGNATURE",
    "nonce": "a3f1c0d9e8b7a6f5e4d3c2b1a0998877665544332211ffeeddccbbaa99887766",
    "status": "FAILED",
    "recoveredAddress": "0xab8483f64d9c6d1ecf9b849ae677dd3315835cb2",
    "failureReason": "ADDRESS_MISMATCH",
    "verifiedAt": null,
    "verifiedWalletId": null
  }
}

Use the API to release withdrawals

Use the events to update your interface and your records. When releasing a withdrawal, keep calling GET /v1/wallets, which also accounts for revocations made after the proof.