Developer docs

Receivers

The URLs StreamAgent listens on. Revenue sources report purchases and refunds into the outcomes ledger against the lead who watched; scheduling tools confirm bookings so a lead is stamped as booked. Every receiver is per workspace and verified by a secret; the URL itself carries no trust.

Revenue sources

Connect a source under Integrations → Revenue. Stripe and ClickFunnels connect in one click (Stripe Connect, and the ClickFunnels connection from the platforms section); when that path cannot complete, the card opens the manual form instead. Shopify asks for its webhook signing secret, and the generic source mints a secret for you and shows it once. Whichever way a source connects, the manual endpoint below stays valid: point the provider at it yourself and paste its signing secret if you would rather not connect the account. The endpoint shape is the same for all four:

https://app.streamagent.io/api/webhooks/outcomes/{provider}?ws={workspace id}
ProviderSignature headerRecordsReverses
Stripestripe-signaturecheckout.session.completed (mode=payment), invoice.paidcharge.refunded
ClickFunnelsx-webhook-clickfunnels-signatureone-time-order.completedone_time_order.refunded
Shopifyx-shopify-hmac-sha256orders/paidrefunds/create, orders/cancelled
Any systemx-streamagent-signaturepurchase, customrefund

A recorded outcome lands as outcome.recorded on your webhooks and in the revenue figures on the dashboard. Provider retries are recognised by the provider's own id and answered as duplicates; unrelated events are acknowledged and ignored so the provider does not retry them.

Stripe Connect

Connect Stripe on the Revenue card authorizes StreamAgent on your own Stripe account (Stripe Connect, OAuth). You pick the account on Stripe's page; on return the card reads "Connected via Stripe · acct_…" with that account's id. Stripe then delivers the account's events to StreamAgent itself: there is no endpoint to create and no secret to paste, and a sale does not have to start inside StreamAgent to count.

Stripe eventWhat happens
checkout.session.completed, mode=payment, payment_status=paidA purchase for amount_total in the session's currency; the payment intent is kept as the reference a refund can name.
checkout.session.completed in subscription or setup modeIgnored: the payment is recorded from its invoice.paid, so the first payment is never doubled.
invoice.paidA purchase for amount_paid, labeled by billing_reason unless metadata.sa_label is set. Zero-amount invoices are ignored.
charge.refunded with refunded=trueReverses the purchase whose payment intent (or invoice) the charge names.
charge.refunded for a partial refundIgnored: the purchase stands at its sale value.
account.application.deauthorizedYou removed StreamAgent from inside Stripe: the connection is marked disconnected and the source paused. Reconnect from the card.

Matching: the buyer's checkout email (customer_details.email, or the invoice's customer_email) is matched against the workspace's leads. For an exact match from a checkout you build, set client_reference_id to the StreamAgent lead id, or metadata.sa_lead_id on the session, the invoice, or the subscription. metadata.sa_label names the purchase in the ledger. Amounts are recorded in the currency Stripe reports, so a buyer who paid in a local currency shows in that currency.

The generic revenue source

Any system that can POST JSON can report revenue. Sign the raw body the way StreamAgent signs its own webhooks: an X-StreamAgent-Signature header of t=<unix ms>,v1=<hex HMAC-SHA256 of "<t>.<body>"> using the secret the card minted. The verification is the mirror of the one on the Webhooks page.

FieldRequiredNotes
eventyespurchase, custom or refund.
idyesYour id for the order. Repeats are treated as the same outcome; a refund names the order it reverses.
amount_cents or amountpurchase, customInteger cents, or a decimal amount in the currency.
currencynoThree-letter code, USD when omitted.
labelnoUp to 120 characters, shown in the ledger.
emailnoUsed to match the lead when lead_id is absent.
lead_idnoA StreamAgent lead id, when you have it.
occurred_atnoISO 8601; now when omitted.
refnoA secondary reference, kept with the outcome.
{
  "event": "purchase",
  "id": "ord_10492",
  "amount_cents": 49900,
  "currency": "USD",
  "label": "Annual plan",
  "email": "maria@example.com",
  "occurred_at": "2026-09-07T14:03:11.412Z",
  "ref": "inv_88a1"
}
A purchase
{
  "event": "refund",
  "id": "ord_10492",
  "occurred_at": "2026-09-08T09:15:00.000Z"
}
A refund of the same order

Scheduling tools

When a Book a call element uses your own Calendly or Cal.com page, the booking still lands in StreamAgent once the tool is connected on the Integrations page.

ToolHow it connectsWhat you configure
CalendlySign in from the Calendly card; StreamAgent creates the webhook subscription itself and stores its signing key.Nothing. Deliveries are verified with the calendly-webhook-signature header.
Cal.comPaste a signing secret you choose into the Cal.com card; the connected card shows the receiver URL.In Cal.com, create a webhook at https://app.streamagent.io/api/webhooks/calcom?ws={workspace id} with the same secret and enable Booking Created and Booking Cancelled. Deliveries are verified with X-Cal-Signature-256.
  • A created booking resolves or creates the lead from the invitee's email, name and phone, stamps the booking, and fires booking.created on your webhooks.
  • A cancellation un-books the lead and fires booking.canceled.
  • Reschedules and other triggers are acknowledged without changes.