Skip to content
← All recipes

Dividends & Corporate Actions

≈ half a day

Two webhook streams keep client portfolios truthful: dividend.paid announces cash that has already been credited, and corporateaction.declared warns you that units, symbols, or prices are about to change shape. Apps that ignore the second one show wrong quantities after every stock split.

The flow

StepEndpoint / EventWhat it does
1GET /dividends/calendarUpcoming declarations. Filter on partnerEligible: true — set when at least one of your sub-accounts holds the stock.
2GET /users/{id}/dividendsPer-user dividend income history with per-share amounts and pay dates.
3Webhook: dividend.paidOne event per distribution batch, grouped by symbol, with a distributions[] array of every credited sub-account.
4Webhook: corporateaction.declaredSplit / rights / bonus / merger / delisting / symbol change, with type, exDate, payDate, ratio, and affectedSubAccounts[].
5Apply the actionUpdate cached units, symbols, and cost display in your app; the platform adjusts holdings and tax lots on its side.
6GET /report/dividendsPartner-level dividend report for finance, with CSV export.

Implementation

javascript
// Inside your webhook handler (see "Handle Webhooks Reliably" for the shell):
async function processEvent(event) {
  switch (event.event) {
    case 'dividend.paid': {
      // Wallets are ALREADY credited — display + notify only.
      const { symbol, dividendPerShare, distributions } = event.data;
      for (const d of distributions) {
        await notifyUser(d.externalId,
          `Dividend: ${symbol} paid ${dividendPerShare}/share — $${d.usdYield} credited.`);
      }
      break;
    }
    case 'corporateaction.declared': {
      const { type, symbol, ratio, exDate, affectedSubAccounts } = event.data;
      // e.g. a 4:1 SPLIT — refresh cached holdings for affected users after exDate.
      for (const a of affectedSubAccounts) {
        await invalidatePortfolioCache(a.subAccountId);
        await notifyUser(a.externalId,
          `${symbol}: ${type} effective ${exDate}${ratio ? ` (ratio ${ratio})` : ''}.`);
      }
      // SYMBOL_CHANGE: remap any watchlists / references you store by ticker.
      break;
    }
  }
}

Common mistakes

  • Ignoring corporateaction.declared. After a split, every cached quantity and average cost you display is wrong until you refresh from GET /users/{id}/portfolio.
  • Crediting dividend cash yourself — the platform already moved the money; double-crediting your own ledger is the classic reconciliation break.
  • Treating dividend.paid as one event per user. It is grouped by symbol with a distributions[] array — iterate it.
  • Storing watchlists and references by ticker without handling SYMBOL_CHANGE actions.
  • Showing calendar entries for stocks none of your users hold — filter on partnerEligible.

Prove it in sandbox first

  • 1.Dividend and corporate-action processing run on production data; in sandbox, exercise your handler with POST /webhooks/{id}/test and hand-crafted payloads matching the documented shapes.
  • 2.Replay past real events from GET /webhooks/{id}/deliveries once you have a live key.