Testing

Test the canonical Server API path first. The important gates are key class, /v1/placements response shape, hosted renderer behavior, consent, and beacons. The advanced SDK should only be tested after the core API path is already green.

Test safely

Environments and credentials

Test/Sandbox

Use a Server Test Key (sk_test_...) for integration checks. Test/Sandbox traffic is non-billable, including validation and guardrail diagnostics.

Production dry-run

Use a Server Production Dry-run Key (sk_dry_...). Dry-run is selected by credential class, remains non-billable, and requires no payout setup.

Live boundary

Do not send production_dry_run, production_billing_dry_run, billing_suppressed, or production_live_approved in public request bodies. Billable production/live traffic requires payout readiness, SSP readiness, proof, and explicit live approval.

Credential classes

Dashboard API Keys separates Server Test Key (sk_test_...), Server Production Dry-run Key (sk_dry_...), Server Production Key, and Browser Publishable Key. Do not reuse one class for another environment.

Secret visibility

Raw server secrets are shown only once after create or rotate. Existing masked server-secret previews identify a key but are not usable credentials; create or rotate a server key when you need the full value.

Checklist

Minimum validation path

Use test keys

Use sk_test_*, publishable test keys, and the same Project ID (client_id, WAVEBIRD_CLIENT_ID) first so you can validate the full route chain without billing traffic. In Dashboard API Keys, create or rotate a Server Test Key to copy the full backend-only value; masked previews are for identification and cannot be used as credentials.

Keep key classes separate

Use Server Test Key (sk_test_...) for Test/Sandbox, Server Production Dry-run Key (sk_dry_...) for non-billable dry-run, Server Production Key only after live approval, and Browser Publishable Key only for browser activation. Raw server secrets are shown only once after create or rotate; masked server-secret previews are not usable credentials.

Exercise no-fill and fill

Do not test only the happy path. Validate both filled decisions and no-fill states for your configured formats and constraints.

Exercise optional fields

Test prompt, slot_hint, request-level consent, and advanced overrides separately. Validation errors include request_id and field paths such as slot_hint.max_width.

Confirm beacons

Check rendered and completion beacons for the formats you actually ship. Billing evidence depends on that path, not just on placement creation.

Script Tag

Browser-specific checks

Verify activation against the expected origin, validate consent-required behavior, and confirm that the browser receives only the runtime-safe project config for the active client_id.

Sandbox

Expected negative tests

Beacon validation failures

Intentionally missing asset_token, missing slot_id, invalid event, or stale occurred_at requests should return actionable 400 validation errors in sandbox tests.

A stale timestamp can return BEACON_TOO_LATE. Generate a fresh timestamp for every direct server beacon with new Date().toISOString().

Consent validation failures

Invalid consent purposes should return field-level validation errors. These are expected negative tests when deliberately triggered and should not be treated as production integration failures.

Hosted renderer first

Default integrations should rely on hosted renderer beacons sent to /public/wrapper/v1/beacons. Direct server /v1/beacons is an advanced QA or custom-rendering path.

Direct beacon token handling

Direct server beacons require the sensitive asset_token from placement.asset_token or decision.asset_token. Redact it from logs, screenshots, reports, and client-visible debug output.

Sandbox

Renderer proof diagnostics

Hosted renderer beacons are accepted for sandbox QA even when they are not proof-eligible or billable. Dashboard logs may expose safe diagnostic fields such as proof_source=public_wrapper_renderer, proof_eligible=false, billable=false, non_billable_reason, geometry_reason, renderer_diagnostic_case, contract_exists=true, and renderer_geometry_summary.

Production dry-run validation is still non-billable. Create a Server Production Dry-run Key from Dashboard API Keys, or request one from your wavebird operator, and use the sk_dry_... value as your server-side WAVEBIRD_SECRET_KEY. When dry-run flags or a dry-run key are active, qualifying hosted renderer proof should 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 and production-live-approved is not used for dry-run QA.

If no active SSP demand is available for a production dry-run placement, the placement response should use 409 ssp_not_ready with mode=production-dry-run, production_dry_run=true, production_live_approved=false, and billable=false. Treat that as a dry-run availability/setup blocker, not as a live billing failure.

CaseExpected reasonUse in QA
tinyINSUFFICIENT_VISIBLE_AREAPositive but too-small visible geometry, such as a 1x1 diagnostic slot.
clipped_8x1_25INSUFFICIENT_VISIBLE_AREAA clipped renderer row with visible/intersection geometry below the paid contract.
hidden or opacity_zeroHIDDEN_OR_NOT_VIEWABLECSS-hidden or transparent renderer evidence that must remain non-billable.
offscreenOFFSCREENRenderer evidence outside the viewport or intersection path.

Pre-live

Production dry-run contract

Use the dry-run server key

Production dry-run is a public pre-live validation mode selected by credential class, not by a request-body flag. Use an authorized Server Production Dry-run Key (sk_dry_...) for normal server-side /v1/placements calls. Do not send undocumented production_dry_run, production_billing_dry_run, billing_suppressed, or production_live_approved fields in request bodies; those names are response, log, or dashboard diagnostics only.

Stop at lock-state when gated

If Dashboard shows Phase 4, SSP readiness, payout, or live approval as locked or pending, external preflight tests should verify the visible lock-state and stop unless an authorized dry-run key is available. Test/Sandbox remains the public validation path until production dry-run is explicitly available.

Expect safe blocked responses

A dry-run placement with no active SSP readiness should fail closed with 409 ssp_not_ready. The expected safe response/log semantics are production_dry_run=true, production_billing_dry_run=true, billing_suppressed=true, production_live_approved=false, live_billing=false, and billable=false.

Live billing stays separate

Payout setup is not required for production dry-run. Payout readiness, SSP readiness, and explicit production live approval are required before any billable production/live traffic. Do not use production live keys, click real ads, or claim production billing readiness from dry-run output.

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