Lead Scoring v2: Omni integration
AI Platform publishes this provider contract; Omni implements its consumer. openapi.json is generated from backend routes. The JSON files under fixtures/ are examples, not another validation schema. Cross-service acceptance still requires Omni to run them.
Terminal notification
When AI_PLATFORM_WEBHOOK_URL and AI_PLATFORM_WEBHOOK_SIGNING_SECRET are both configured, AI Platform sends POST to that one server-side URL with Content-Type: application/json. The raw UTF-8 body contains exactly event_id (stable across retries), run_id, tenant_id, status (completed or failed), and occurred_at (UTC ISO 8601). It contains no run result, snapshot, tenant key, V-Key, or AI evidence. occurred_at is the terminal event time; it is not the send time.
X-Webhook-Timestamp is the UTC ISO 8601 time of this delivery attempt. X-Webhook-Signature is sha256= followed by the lowercase hex HMAC-SHA256 of the UTF-8 bytes timestamp + "." + raw_request_body, using the shared signing secret. Verify the signature over the raw body before parsing JSON, compare in constant time, and reject timestamps outside a five-minute window. The sample in fixtures/webhook-delivery.json uses the test-only secret test-only-webhook-secret-32-characters-long and fixes the exact bytes and signature.
Omni must deduplicate by event_id and handle delivery retries without rescoring. Return any 2xx only after durably accepting the event; AI Platform retries non-2xx or network failures up to five total attempts, then marks the outbox event dead. The receiver uses its tenant key to GET /v1/lead-scoring/runs/{run_id}, checks tenant and terminal status, and applies its own latest-run-per-(tenant, subject) policy before writing to DotB EMS. The GET response is the result source of truth. Delivery may be repeated after a crash even if Omni previously replied 2xx.
Only enable the integration after Omni verifies this fixture, timestamp/replay handling, duplicate delivery and GET/writeback against its consumer. The webhook URL, signing secret and tenant key belong in server-side configuration; never put them in browser code.