Skip to main content
The Headless API mode lets your UI call BarkerEngine directly with the user’s wallet. After the user signs a deposit or redeem transaction, your frontend sees the tx hash immediately — but the position is not “real” until the on-chain log is confirmed and we’ve notified you. This page documents the event sequence so you can show “pending” / “confirmed” states correctly without hammering /position.

Why lifecycle webhooks (vs polling /position)

The /position endpoint reads balanceOf + convertToAssets directly from the chain — accurate but expensive to poll, and it doesn’t tell you which transaction caused the change. Lifecycle webhooks give you:
  • A push signal the moment a deposit or redeem hits confirmation depth (no polling)
  • The originating tx_hash so you can join with your own pending-tx table
  • The exact shares / amount so you can update your DB without a follow-up RPC call
Use lifecycle webhooks for state transitions, use /position for total balance display.

Sync vault sequence

Most BarkerEngine products wrap a synchronous ERC-4626 vault — deposit() returns shares atomically, redeem() returns assets atomically.

Deposit

Events fired:
  1. deposit.confirmed — fires once, after the Deposit(sender, owner, assets, shares) log reaches confirmation depth.

Redeem

Events fired:
  1. redeem.confirmed — fires once, after the Withdraw(sender, receiver, owner, assets, shares) log reaches confirmation depth.

Async vault sequence

Some underlying vaults (e.g. liquid-staking with unbond periods, certain Morpho strategies) cannot redeem atomically — the user submits a request, settlement happens later. BarkerEngine wraps this with two events. Events fired:
  1. redeem.requested — fires after RedeemRequested(request_id, owner, shares) log. Includes estimated_settlement_at (computed from the underlying vault’s unbond period).
  2. redeem.confirmed — fires when the settlement Withdraw log appears. The tx_hash here is the settlement tx, not the request tx.
You can correlate the two via the user_address + shares (or query /position to confirm). A product is sync vs async based on the underlying vault — check the redeem_mode field on the product detail endpoint (sync | async). Sync products never emit redeem.requested.

Confirmation depth

Engine logs are not delivered until they’re deep enough that a chain reorg is unlikely to drop them.
Chainchain_idDepthApprox. delay
Ethereum mainnet112 blocks~3 min
Base845332 blocks~1 min
Arbitrum One4216132 blocks~10 sec
Optimism1032 blocks~1 min
Polygon PoS13764 blocks~2 min
Sandbox testnets11155111, 84532, etc.1 block~12 sec
These are the defaults. The exact value used for delivery is included in the engine health endpoint (GET /api/partner/products/{slug}/health) under confirmation_depth_blocks so you can compute the same “still pending” cutoff in your UI.

Reconciling with /position

After you handle deposit.confirmed you generally don’t need to call /position — the event payload already has the new shares and amount. But for a sanity check or when you reconnect after downtime:
  • /position returns the current chain state, not a snapshot at the event time
  • For a user who just deposited and immediately withdrew, the events arrive in order but /position reflects the net (zero)
  • The webhook’s block_number lets you order events; do not rely on delivery order alone (retries can shuffle)

Edge cases

Chain reorg below confirmation depth. The reorg happens before we deliver — no event fires for the orphaned tx. The user’s wallet shows the tx as dropped; your UI should treat tx-without-event as a failure once you exceed confirmation_depth_blocks * 2 * block_time since submission. Multiple deposits in the same tx (multicall). Each Deposit log produces one deposit.confirmed. The log_index differentiates them within the tx. Same user, multiple products in one tx. Same as above — one event per log. The slug field tells you which product. Engine paused mid-deposit. The deposit either reverts (no event) or completes (normal deposit.confirmed) — pause prevents new deposits but doesn’t void in-flight ones. After pause, the next event you’ll see for that product is vault_pause. Redeem requested then user changes mind. Most async vaults don’t support cancellation. If they do, you’ll see neither redeem.confirmed nor a cancel event in v1; the request quietly disappears from the underlying vault. Until cancellation events ship, reconcile via /position.

What’s next

  • Failure modes — RPC outages, tx replacement, webhook delivery failure, idempotency
  • Webhooks — signature verification, retry policy, dedupe keys
  • Headless integration — wallet-side deposit/redeem code samples