Revenue API Reference#

All revenue events are sent to POST /api/ingest with the following schema. This page documents both the @pulsora/revenue SDK methods and the raw HTTP payload.

SDK: revenue.track(data)#

import { Revenue } from '@pulsora/revenue';

const revenue = new Revenue({ apiToken: 'sec_123' });

await revenue.track({
  visitor_fingerprint: 'fp_abc',
  session_id: 'sess_xyz',
  customer_id: 'cus_42',
  amount: 499.0,
  currency: 'USD',
  transaction_id: 'ch_1Nv…',
  payment_processor: 'stripe',
  event_type: 'purchase',
  metadata: {
    plan: 'pro',
    seats: 10,
  },
});

Accepted Fields#

Field Type Required Description
visitor_fingerprint string Fingerprint from @pulsora/core.
session_id string Session ID from @pulsora/core.
customer_id string Your internal customer identifier.
amount number Gross revenue amount. Positive numbers only.
currency string ISO currency code (default: USD).
transaction_id string Unique transaction reference (payment intent, invoice, etc.).
payment_processor string e.g. stripe, paddle, chargebee.
event_type string One of purchase, subscription, renewal, upgrade, downgrade, churn, refund.
customer_subscription_id string Subscription identifier (if applicable).
mrr_impact number Monthly recurring revenue delta (positive/negative).
is_recurring boolean Set to true for recurring charges.
metadata Record<string, any> Additional context (plan name, coupon, campaign, etc.).

Validation errors throw descriptive exceptions in the SDK (and return 400 from the API when using raw requests).

Raw HTTP Payload#

If you prefer to call the ingest endpoint yourself, send a JSON payload with a secret token:

POST https://pulsora.co/api/ingest
X-API-Token: sec_123
Content-Type: application/json

{
  "type": "revenue",
  "token": "sec_123",
  "data": {
    "visitor_fingerprint": "fp_abc",
    "session_id": "sess_xyz",
    "customer_id": "cus_42",
    "amount": 499,
    "currency": "USD",
    "transaction_id": "ch_1Nv...",
    "payment_processor": "stripe",
    "event_type": "purchase"
  }
}

Responses#

Status Body Meaning
202 Accepted { "success": true } Event queued for processing successfully.
400 Bad Request { "message": "...validation..." } Missing required fields or invalid types.
401 Unauthorized { "error": "Invalid API token" } Token missing, malformed, or deactivated.
403 Forbidden { "error": "Revenue events require secret token" } Tried to send revenue with a public token.
429 Too Many Requests { "error": "Rate limited" } + Retry-After header Slow down; Pulsora automatically retries with backoff.

The SDK handles 429 responses with exponential backoff using the maxRetries and retryBackoff configuration.

Event Types#

Event When to Use
purchase One-off purchases, e.g. lifetime deals, add-ons, or invoices.
subscription New subscription signups (first charge).
renewal Recurring subscription renewals on the same plan.
upgrade Customer moves to a higher plan or adds seats (positive MRR impact).
downgrade Customer moves to a lower plan (negative MRR impact).
churn Subscription cancelled or expired (set mrr_impact negative).
refund Refund issued for a previous payment.

Each event type feeds different dashboards (MRR, churn, expansion, contraction). For churn/refund, send a negative mrr_impact / amount if needed.

Metadata Conventions#

Metadata is optional but extremely powerful. Recommended keys:

  • plan — Plan or SKU the customer purchased.
  • intervalmonthly, annual, etc.
  • coupon — Discount code applied.
  • source — e.g. partner, sales, self-serve.
  • campaign — Marketing campaign for internal alignment.

Metadata is stored in Pulsora and searchable in the revenue explorer.

Error Handling#

Wrap track() calls in try/catch to surface issues to your monitoring stack:

try {
  await revenue.track(payload);
} catch (error) {
  logger.error('Failed to send revenue event', { error, payload });
  throw error; // or handle gracefully
}

For more implementation patterns, jump to the revenue examples →