Skip to main content

Ads serving

Sellable product

This capability is granted by an API key scoped to the `` product (product face). See the product reference below.

Shared ad-serving capability. Direct-sold campaign lifecycle + serve (premium-exclusion, date-gating, budget-exhaustion, frequency-cap) + impression/click recording with per-campaign budget decrement + CTR; tiered sponsored-listing serve mechanism (per-page cap, expiry window, tier-rank order, is_sponsored); and a newsletter sponsor block served from the listing store. Recording an event decrements the campaign's remaining budget in this service's own store and EMITS an ad event that the revenue-tracking sibling ledgers — ads-serving never writes the cross-provider revenue ledger.

  • Group: Commerce & revenue
  • Contract: contracts/ads-serving/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/ads/campaigns

Endpoints

MethodPathSummary
POST/v1/campaignsCreate an ad campaign (direct-sold engine) — org-scoped
GET/v1/campaignsList campaigns for the org (optional status/advertiser filters)
GET/v1/campaigns/&#123;campaign_id&#125;Get a campaign
PUT/v1/campaigns/&#123;campaign_id&#125;Update a campaign (whitelisted fields)
DELETE/v1/campaigns/&#123;campaign_id&#125;Soft-delete a campaign (status -> deleted)
GET/v1/campaigns/&#123;campaign_id&#125;/statsCampaign CTR + budget stats
GET/v1/placementServe an ad placement for the org context — premium-exclusion, active + in-window + budget-not-exhausted + frequency-cap-not-reached. Returns {ad:null, reason} when nothing servable.
POST/v1/impressionRecord an impression — increments count, decrements campaign budget, emits to revenue sibling
POST/v1/clickRecord a click — increments count, decrements campaign budget, emits to revenue sibling
POST/v1/listingsCreate a sponsored directory listing (tiered-listing MECHANISM). tier is an OPAQUE string; tier_rank is the ordering weight and price_monthly_usd/features are optional metadata the DOMAIN caller passes — the capability hardcodes no tier price or editorial copy (those stay platform domain).
GET/v1/listings/activeActive sponsored listings for the org, tier-rank ordered, capped per page (expiry-window filtered)
GET/v1/listings/is-sponsoredWhether a source currently has an active sponsorship (org-scoped)
GET/v1/newsletter/sponsor-blockServe the newsletter sponsor block for an edition from the active listing store (top active listing becomes the sponsor; else sponsor:null — behavior-compatible with the platform's prior static stub).
POST/v1/native/placementsUpsert a native placement CONFIG (org-scoped). The seam the DOMAIN caller uses to SEED its placement definitions into core — the LABELS/copy are domain data it pushes; core stores placement_type as an opaque string and keeps the serve mechanism. Idempotent on (organization_id, placement_id).
GET/v1/native/placementsServe active native placement configs for a page context (superset of NativeAdService.get_placements MECHANISM). page_type -> allowed placement types (article+article_id -> below_article/sidebar/ end_of_article; home/category/search -> in_feed/sidebar; other -> all active); capped at 20. Returns an empty list when the org has no matching placements — the domain caller supplies its own defaults.
POST/v1/native/impressionRecord a PLACEMENT-keyed native impression (telemetry-only; no budget) — emits to revenue sibling
POST/v1/native/clickRecord a PLACEMENT-keyed native click (telemetry-only; no budget) — emits to revenue sibling
GET/v1/native/performanceAggregate native-ad performance by placement (superset of NativeAdService.get_performance_metrics). CTR is the RATIO clicks/impressions (rounded to 4), matching the native facade — not the campaign engine's percentage form. Empty -> zeroed totals, never an error.
GET/healthliveness + store/tenancy posture
GET/metricsPrometheus exposition

Schemas

CampaignCreate

FieldTypeDescription
organization_idstringend-customer tenant (I6); resolved/verified server-side, never trusted raw
advertiser_idstring
namestring
contentobject
budgetnumber
start_datenumberepoch seconds
end_datenumberepoch seconds
categorystring
target_audiencestring
frequency_capinteger

Campaign

FieldTypeDescription
campaign_idstring
organization_idstring
advertiser_idstring
namestring
contentobject
budgetnumber
spentnumber
impressionsinteger
clicksinteger
statusstring
start_datenumber
end_datenumber
categorystring
target_audiencestring
frequency_capinteger

AdEvent

FieldTypeDescription
organization_idstring
campaign_idstring
article_idstring
user_idstring

ListingCreate

FieldTypeDescription
organization_idstring
source_idstring
sponsor_idstring
tierstringopaque tier string — the capability stores it, prices stay domain
tier_rankintegerordering weight (premium>featured>basic) passed by the domain caller
categorystring
price_monthly_usdnumberoptional metadata passed by the domain caller; not hardcoded here
featuresarray
expires_atnumberepoch seconds

NativePlacementUpsert

FieldTypeDescription
organization_idstringend-customer tenant (I6); resolved/verified server-side, never trusted raw
placement_idstring
placement_typestringopaque position string (e.g. below_article/sidebar/in_feed/end_of_article) — the page-context serve map matches on it; core hardcodes no label
labelstringdisplay copy — DOMAIN data the caller seeds; core stores it opaquely
providerstring
max_unitsinteger
activeboolean
metadataobjectzero-loss bag for any extra domain config fields

NativePlacement

FieldTypeDescription
placement_idstring
organization_idstring
placement_typestring
labelstring
providerstring
max_unitsinteger
activeboolean

NativeAdEvent

FieldTypeDescription
organization_idstring
placement_idstring
article_idstring
user_idstring
site_idstringper-domain revenue dimension (preserved for the revenue read repoint)
ad_idstring

Error

FieldTypeDescription
errorstringstable machine code (e.g. validation_error, not_found, unauthorized)
reasonstringhuman-readable one-line explanation (no secrets/PII)
detailobject
request_idstring

Generated by scripts/gen-capability-docs.py from contracts/ads-serving/v1/openapi.yaml — the contract IS the source of truth; edit the contract, not this page.