Staking

Webhook Event Configuration

Set up webhook endpoints to receive real-time notifications for staking events. Configure your webhook URL and specify which events to receive.

{
  "webhook_url": "https://yourapi.com/webhooks/staking",
  "events": [
    "stake.submitted",
    "stake.canceled",
    "stake.broadcasted",
    "stake.confirmed",
    "stake.staked",
    "stake.failed",
    "staking_reward.received",
    "unstake.submitted",
    "unstake.canceled",
    "unstake.broadcasted",
    "unstake.confirmed",
    "unstake.unstaked",
    "unstake.failed"
  ]
}

Webhook Event Reference

stake.submitted

Sent immediately after stake request is accepted and queued for processing.

{
  "event_type": "stake.submitted",
  "timestamp": "2026-05-21T16:00:00.123Z",
  "occurred_at": "2026-05-21T16:00:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "amount": "10.5",
  "status": "submitted",
  "activation_period_days": 30,
  "estimated_active_at": "2026-06-20T16:00:00.123Z"
}

stake.queued

Sent when the stake enters the batch queue awaiting the next submission window.

{
  "event_type": "stake.queued",
  "timestamp": "2026-05-21T16:01:00.123Z",
  "occurred_at": "2026-05-21T16:01:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "status": "queued"
}

stake.canceled

Sent immediately after stake request is canceled.

{
  "event_type": "stake.canceled",
  "timestamp": "2026-05-21T16:02:00.123Z",
  "occurred_at": "2026-05-21T16:02:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "amount": "10.5",
  "status": "canceled",
  "reason": "user_initiated"
}

stake.broadcasted

Sent when the stake transaction is signed and broadcast to the network.

{
  "event_type": "stake.broadcasted",
  "timestamp": "2026-05-21T16:05:00.123Z",
  "occurred_at": "2026-05-21T16:05:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "status": "broadcasted"
}

stake.confirmed

Sent when the stake enters the consensus activation queue and pool allocation begins. On-chain broadcast confirmation is stake.broadcasted.

{
  "event_type": "stake.confirmed",
  "timestamp": "2026-05-21T16:15:00.123Z",
  "occurred_at": "2026-05-21T16:15:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "amount": "10.5",
  "status": "confirmed",
  "tx_hash": "0xabc...",
  "activation_period_days": 30,
  "estimated_active_at": "2026-06-20T16:00:00.123Z"
}

stake.staked

Sent when the stake completes activation and begins earning rewards.

{
  "event_type": "stake.staked",
  "timestamp": "2026-05-28T12:00:00.123Z",
  "occurred_at": "2026-05-28T12:00:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "amount": "10.5",
  "status": "staked",
  "tx_hash": "0xabc..."
}

stake.failed

Sent when the stake request fails. Includes a reason field for diagnostics.


{
  "event_type": "stake.failed",
  "timestamp": "2026-05-21T16:10:00.123Z",
  "occurred_at": "2026-05-21T16:10:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "stake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06754e",
  "asset": "ETH",
  "amount": "10.5",
  "status": "failed",
  "reason": "pool_capacity_exceeded"
}

staking_reward.received

Sent when staking rewards are distributed and credited to the participant's account.

{
  "event_type": "staking_reward.received",
  "timestamp": "2026-05-22T12:00:00.123Z",
  "credited_at": "2026-05-22T12:00:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "distribution_id": "dist_abc123",
  "asset": "ETH",
  "status": "credited",
  "reward_amount": "0.025",
  "cumulative_rewards_amount": "0.125"
}

unstake.submitted

{
  "event_type": "unstake.submitted",
  "timestamp": "2026-05-30T10:00:00.123Z",
  "occurred_at": "2026-05-30T10:00:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "amount": "10.5",
  "status": "submitted",
  "cooldown_period_days": 7,
  "estimated_available_at": "2026-06-06T10:00:00.123Z"
}

unstake.queued

Sent when the unstake enters the batch queue awaiting the next submission window.

{
  "event_type": "unstake.queued",
  "timestamp": "2026-05-30T10:02:00.123Z",
  "occurred_at": "2026-05-30T10:02:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "status": "queued"
}

unstake.canceled

{
  "event_type": "unstake.canceled",
  "timestamp": "2026-05-30T10:01:00.123Z",
  "occurred_at": "2026-05-30T10:01:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "amount": "10.5",
  "status": "canceled",
  "reason": "user_initiated"
}

unstake.broadcasted

{
  "event_type": "unstake.broadcasted",
  "timestamp": "2026-05-30T10:05:00.123Z",
  "occurred_at": "2026-05-30T10:05:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "status": "broadcasted"
}

unstake.confirmed

Sent when the unstake enters the exit queue (cooling-down).

{
  "event_type": "unstake.confirmed",
  "timestamp": "2026-05-30T10:15:00.123Z",
  "occurred_at": "2026-05-30T10:15:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "amount": "10.5",
  "status": "confirmed",
  "tx_hash": "0xdef...",
  "cooldown_period_days": 7,
  "estimated_available_at": "2026-06-06T10:00:00.123Z"
}

unstake.unstaked

Sent when unstake period completes and funds are returned to the available account.

{
  "event_type": "unstake.unstaked",
  "timestamp": "2026-06-03T08:00:00.123Z",
  "occurred_at": "2026-06-03T08:00:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "amount": "10.5",
  "status": "unstaked"
}

unstake.failed

Sent when the unstake request fails. Includes a reason field for diagnostics.

{
  "event_type": "unstake.failed",
  "timestamp": "2026-05-30T10:10:00.123Z",
  "occurred_at": "2026-05-30T10:10:00.123Z",
  "participant_code": "CUST01",
  "account_label": "general",
  "unstake_id": "c761fc96-5c44-40d4-8eb2-3fcd5d06757d",
  "asset": "ETH",
  "amount": "10.5",
  "status": "failed",
  "reason": "exit_queue_full"
}

Implementation Best Practices

  • Acknowledge immediately: Always return 200 OK to acknowledge webhook receipt
  • Process asynchronously: Handle webhook processing outside the request/response cycle to avoid timeouts
  • Store payloads: Maintain webhook event logs for debugging and audit trails
  • Handle duplicates: Implement idempotency. For reward events, use distribution_id. For stake and unstake events, use stake_id/unstake_id combined with status.
  • Fallback strategy: Implement polling as a backup if webhook delivery fails
  • Verify authenticity: Validate webhook signatures to ensure requests come from zerohash
  • Monitor failures: Track webhook delivery failures and alert on persistent issues