This capability is granted by an API key scoped to the `` product (product face). See the product reference below.
Shared cross-provider revenue LEDGER capability. Records revenue events (native first-party shape OR the ads-serving / affiliate sibling emit envelopes) into one org-scoped store, and serves a multi-dimensional aggregation (by_type / by_provider / by_channel / by_site + ad/subscription split + this_month + CPM/CPC imputed telemetry) with an optional user_id scope for the per-user breakdown, plus a recent-event feed. The event-type / provider / channel registries and the imputation rates are config-driven.
- Group: Commerce & revenue
- Contract:
contracts/revenue-tracking/v1/openapi.yaml
- Public base:
https://api.vagarylabs.com (the consolidated API gateway — one host, per-brand sibling api.<zone>)
- Auth: a product API key (
vgk_…) issued from the console — Authorization: Bearer vgk_…
- Product face (customer-keyed):
https://api.vagarylabs.com/product/v1/revenue/events
Endpoints
| Method | Path | Summary |
|---|
POST | /v1/revenue/events | Record a revenue event. Accepts the NATIVE revenue-event shape, or an ads-serving emit ({source:ads-serving, campaign_id, event_type:impression |
| | |
GET | /v1/revenue/events | Recent-event feed (org-scoped), newest-first, optionally site-filtered — ports RevenueTrackingService.get_recent_events. |
| | |
GET | /v1/revenue/summary | Aggregated revenue summary — the SUPERSET read surface. With no scope it is platform-wide (by_site + ad/subscription split + this_month + imputed ETL, = get_platform_revenue); site_id scopes to one site (by_type/by_provider, = get_revenue_summary); user_id scopes to one user (by_channel, = get_user_revenue_breakdown). by_channel is always present (= get_revenue_dashboard). Window defaults to 30 days. |
| | |
POST | /v1/revenue/erase-subject | GDPR Art-17 subject erasure by PSEUDONYMISATION (first-party admin only) |
GET | /health | liveness + store/tenancy posture |
GET | /metrics | Prometheus exposition |
Schemas
EraseSubjectResult
pseudonymized and deleted are separate fields on purpose: deleted is ALWAYS 0 here because these are statutory-retention financial records. matched is reported separately so a zero-match is visible to the compliance fan-out rather than reading as a successful erasure.
| Field | Type | Description |
|---|
success | boolean | |
capability | string | |
disposition | string | |
selector | string | |
matched | integer | ledger rows belonging to the subject |
pseudonymized | integer | rows whose subject link was severed |
deleted | integer | always 0 — statutory retention forbids deletion |
dry_run | boolean | |
retained_reason | string | the legal basis for retaining the unlinked record |
EventCreate
A native revenue event, or an ads-serving / affiliate sibling emit envelope (discriminated by source). For a sibling envelope only source + event_type (+ the sibling id + optional cost/amount) are needed; the server maps event_type (impression->ad_impression, click->ad_click / affiliate_click, conversion->affiliate_purchase) and stashes campaign_id/affiliate_id/article_id in metadata.
| Field | Type | Description |
|---|
organization_id | string | end-customer tenant (I6); resolved/verified server-side, never trusted raw |
source | string | native |
event_type | string | native canonical type, OR the sibling raw type (impression/click/conversion) |
amount | number | dollars (native/ads cost); 0 for an affiliate click |
cost | number | ads-serving emit budget-accounting amount (mapped to amount) |
provider | string | adsense |
channel | string | the 13-channel dim (from the news facade) |
site_id | string | |
currency | string | |
user_id | string | the per-user dim |
campaign_id | string | ads-serving emit — stashed in metadata |
affiliate_id | string | affiliate emit — stashed in metadata |
article_id | string | sibling emit — stashed in metadata |
event_id | string | idempotency key within (organization_id, source); server-generated if omitted |
metadata | object | |
RecordResult
| Field | Type | Description |
|---|
success | boolean | |
event_id | string | |
Summary
| Field | Type | Description |
|---|
success | boolean | |
organization_id | string | |
site_id | string | |
user_id | string | |
total | number | |
by_type | object | |
by_provider | object | |
by_channel | object | |
by_site | object | |
ad_revenue | number | |
subscription_revenue | number | |
this_month | number | |
event_count | integer | |
period_seconds | integer | |
channel_catalog | array | |
EventFeed
| Field | Type | Description |
|---|
success | boolean | |
count | integer | |
events | array | |
Error
| Field | Type | Description |
|---|
error | string | stable machine code (e.g. validation_error, not_found, unauthorized) |
reason | string | human-readable one-line explanation (no secrets/PII) |
detail | object | |
request_id | string | |
Generated by scripts/gen-capability-docs.py from contracts/revenue-tracking/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page.