Record beacon

POST/v1/beacons

Advanced direct server path. Default integrations should render placement.render with the hosted renderer, which sends browser beacons automatically to /public/wrapper/v1/beacons. Direct beacon writes are for server-rendered, custom-rendered, or QA validation flows; they require the sensitive asset_token returned with the placement or decision and are idempotent by beacon_id.

AUTH

Secret key or browser activation token plus the issued asset_token

CONTENT TYPE

application/json

STATUS

Stable
Secret key or browser activation tokenSandbox thisOpen as Markdown ↗

Request parameters

beacon_id
string
Required
Idempotency key for this beacon event.
slot_id
string
Required
Slot associated with the rendered decision.
asset_token
string
Required
Sensitive asset token issued with the placement response, usually placement.asset_token or decision.asset_token. Required for direct server /v1/beacons; redact it from logs, screenshots, reports, terminal output, external evidence, and client-visible debug output. Do not commit it, do not confuse it with WAVEBIRD_SECRET_KEY/server secret key or publishable key, and do not expose it unnecessarily to frontend code unless required by the hosted renderer flow.
event
string
Required
rendered, visible, clicked, completed, play_started, play_completed, or heartbeat.
occurred_at
string
Required
Fresh ISO timestamp for when the event happened. Generate it at runtime; stale copied sample timestamps can return BEACON_TOO_LATE.
metadata
object
Optional
Optional measurement metadata for the beacon event.

Returns

ok
boolean
True when the beacon request was processed successfully.
accepted
boolean
True when the beacon was accepted.
duplicate
boolean
True when the same beacon_id and event context had already been recorded.
reason_code
string
OK for accepted and duplicate beacons.
proof_source
string
Safe diagnostic source label, for example public_wrapper_renderer for hosted renderer rows or direct_server for advanced direct-server beacon rows.
proof_eligible
boolean
Whether the event currently qualifies as proof. Accepted diagnostics can still be proof_eligible=false.
billable
boolean
Whether the event is billable. Accepted diagnostics and all sandbox/test traffic can still be billable=false.
non_billable_reason
string
Reason an accepted diagnostic is not billable, such as DIRECT_BEACON_NOT_BILLABLE, SANDBOX_NON_BILLABLE, or a geometry reason.
geometry_reason
string
Renderer geometry classification: INSUFFICIENT_VISIBLE_AREA, HIDDEN_OR_NOT_VIEWABLE, OFFSCREEN, RENDERED_SIZE_TOO_SMALL, or NO_RENDERER_GEOMETRY_PROOF.
contract_exists
boolean
Whether the beacon was matched to an internal placement contract for diagnostics/proof evaluation.
renderer_diagnostic_case
string
Safe derived case label for renderer diagnostics, such as clipped_8x1_25, hidden, opacity_zero, ancestor_opacity_zero, offscreen, zero_size, tiny, or normal_visible.
renderer_geometry_summary
object
Safe renderer geometry summary for debugging, including declared, wrapper, target, visible, intersection, opacity, offscreen, cropped, and renderer version fields when available.
mode
string
Safe runtime mode label, such as production-dry-run when production dry-run validation is enabled.
production_dry_run
boolean
True when the event was evaluated under production dry-run mode.
production_billing_dry_run
boolean
True when production billing side effects are suppressed for dry-run validation.
production_live_approved
boolean
False in this dry-run flow. production-live-approved is not used for dry-run QA.
billing_suppressed
boolean
True when dry-run mode suppresses billing side effects.
dry_run_billable_suppressed
boolean
True when proof would otherwise be eligible but billing was suppressed by production dry-run.
proof_would_be_eligible
boolean
True for qualifying renderer proof that would be proof-eligible while remaining non-billable in production dry-run.

Integration guidance

Hosted renderer beacons vs direct server beacons

Most integrations should use the hosted renderer first. Hosted renderer beacons are sent automatically to /public/wrapper/v1/beacons after placement.render is mounted.

For clip placements, the hosted renderer emits play_started and play_completed. Direct server integrations can send play_started and play_completed to /v1/beacons when they own a custom clip renderer.

For native and banner placements, render/click/visibility beacons use the same issued asset_token; native click handling is attached to the hosted native frame overlay.

Use direct /v1/beacons only for advanced server-rendered, custom-rendered, or QA flows. Direct server beacons should not be used to fake or duplicate renderer events except for explicit idempotency or QA testing.

Direct server beacons always require the issued asset_token from placement.asset_token or decision.asset_token.

Direct server beacons are diagnostic/non-billable by default unless a trusted measurement policy explicitly allows them.

PathEndpointCallerUse caseManual code required
Hosted renderer beacons/public/wrapper/v1/beaconsWavebird hosted renderer/browser runtimeDefault measurement/proof pathNo
Direct server beacons/v1/beaconsPublisher serverAdvanced server-rendered/custom-rendered/QA pathYes

Renderer diagnostic outcomes

Accepted renderer diagnostics do not automatically mean proof eligible or billable. Check proof_eligible and billable separately.

INSUFFICIENT_VISIBLE_AREA means the declared creative exists but the measured visible/intersection area was too small, for example because the slot was clipped, cropped, masked, or mostly outside the viewport.

HIDDEN_OR_NOT_VIEWABLE means the renderer evidence indicates display:none, visibility:hidden/collapse, zero/effective opacity, or a hidden/zero-viewable state.

OFFSCREEN means the renderer evidence indicates the slot is outside the viewport. RENDERED_SIZE_TOO_SMALL means the rendered container itself is below the paid-size contract without a clearer clipping signal.

NO_RENDERER_GEOMETRY_PROOF means proof-required geometry was missing. Sandbox/test traffic remains non-billable even when diagnostics are accepted.

renderer_diagnostic_case is a safe derived label that helps identify the exact renderer row during QA without exposing raw tokens, prompts, or private advertiser policy.

Production dry-run is explicitly non-billable. Create a Server Production Dry-run Key in Dashboard API Keys or use an operator-issued sk_dry_... server key as WAVEBIRD_SECRET_KEY.

Production dry-run is selected by credential class, not by request fields. Do not send production_dry_run, production_billing_dry_run, billing_suppressed, or production_live_approved in request bodies; those names are response, log, or dashboard diagnostics only.

A qualifying renderer proof row can expose mode=production-dry-run, PRODUCTION_DRY_RUN_NON_BILLABLE, production_dry_run=true, production_live_approved=false, billing_suppressed=true, dry_run_billable_suppressed=true, and proof_would_be_eligible=true.

No payout setup is required for production dry-run, and production-live-approved is not used. If no active SSP demand is available, the safe blocker is 409 ssp_not_ready with mode=production-dry-run, production_dry_run=true, production_billing_dry_run=true, billing_suppressed=true, production_live_approved=false, live_billing=false, and billable=false.

FieldMeaning
proof_sourceWhere the proof/diagnostic evidence came from, such as public_wrapper_renderer or direct_server.
proof_eligibleWhether the event qualifies as proof after policy and geometry checks.
billableWhether the event can create billable production value.
non_billable_reasonWhy the accepted event is not billable.
geometry_reasonRenderer geometry classification when geometry prevents proof.
contract_existsWhether an internal placement contract was found.
renderer_diagnostic_caseDerived renderer case label, such as clipped_8x1_25, hidden, opacity_zero, offscreen, zero_size, tiny, or normal_visible.
renderer_geometry_summarySafe geometry summary for debugging, without raw tokens or private advertiser policy.
production_dry_runWhether production dry-run mode was active for the event.
production_live_approvedFalse for dry-run QA; production-live-approved is not used.
proof_would_be_eligibleWhether qualifying renderer proof would be eligible if billing were not suppressed by dry-run.
dry_run_billable_suppressedWhether production dry-run suppressed billable side effects for otherwise qualifying proof.

Fresh timestamps and BEACON_TOO_LATE

occurred_at must be close to the real event time. Do not copy old static timestamps from examples.

Generate a fresh timestamp at runtime for every direct server beacon call.

BEACON_TOO_LATE means the event timestamp is too old to be accepted. This commonly happens when testing with copied sample timestamps; use current timestamps for direct server beacon calls.

const occurred_at = new Date().toISOString();

asset_token handling

asset_token is required for direct server /v1/beacons. It is issued with the placement response and is usually available as placement.asset_token or decision.asset_token.

Treat asset_token as sensitive proof material. Redact it from logs, screenshots, reports, support tickets, terminal output, external evidence, and client-visible debug output.

Do not commit asset_token, do not confuse it with WAVEBIRD_SECRET_KEY/server secret key or publishable key, and do not expose it unnecessarily to frontend code unless required by the hosted renderer flow.

Errors

unauthorized401

Missing auth or asset token.

forbidden403

API key or activation token does not match the project that issued the asset_token.

validation_error400

Unsupported event name, malformed body, stale occurred_at / BEACON_TOO_LATE, or slot_id/asset_token mismatch. Errors include field paths.

not_found404

asset_token was not found or is no longer valid.

Related

Need rollout review?

Start with the Server API. Use contact only when you need rollout review, enterprise coordination, or non-standard integration help.

Contact the team