> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pageonetravel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# BRG Radar V2

> Partner integration guide: one browser snippet and one pre-booking API call.

## Partner Integration Requirement

Partner only needs:

1. **One line of code integration**
2. **One API call before booking**

That is the full BRG Radar V2 integration.

## What We Provide vs What Partner Provides

### PageOne Travel provides

* `collector-key` (for browser signal collection only)
* `api-key` (for server-to-server risk check call)
* API host and snippet URL

### Partner provides

* `session-id` (unique per booking attempt)
* Booker/guest data for the check request
* Backend call to `POST /api/v1/radar/checks` before creating booking

## 1) One Line of Code Integration (Snippet)

Add this on the partner booking page:

```html theme={null}
<script async src="https://cdn.pageonetravel.com/brg/radar.min.js" data-session-id="{{SESSION_ID}}" data-collector-key="{{COLLECTOR_KEY}}"></script>
```

Notes:

* Use a fresh `SESSION_ID` per booking attempt.
* Do not put `api-key` in browser code.
* `data-partner-id` is not required.

## 2) One API Call Before Booking

Call this from partner backend before booking confirm:

```http theme={null}
POST /api/v1/radar/checks
```

### Headers

| Header            | Required | Description                              |
| ----------------- | -------- | ---------------------------------------- |
| `Content-Type`    | Yes      | `application/json`                       |
| `api-key`         | Yes      | Partner server API key issued by PageOne |
| `session-id`      | Yes      | Same value used in snippet               |
| `idempotency-key` | No       | Recommended for retry safety             |

### Request body (example)

```json theme={null}
{
  "trigger_event": "booking_before_payment",
  "booker": {
    "first_name": "John",
    "last_name": "Smith",
    "email": "john@example.com",
    "phone": "+12065550123"
  },
  "guest": {
    "first_name": "John",
    "last_name": "Smith"
  },
  "context": {
    "partner_request_id": "req_20260219_001",
    "booker_uuid": "u_abc123",
    "user_id": "12345",
    "ip": "198.51.100.10"
  },
  "payment": {
    "billing_address": {
      "line1": "123 Main St",
      "city": "Seattle",
      "state": "WA",
      "postal_code": "98101",
      "country": "US"
    }
  },
  "extras": {
    "channel": "web"
  }
}
```

`inventory_id` and `inventory_country` are not required from partner in BRG integration.

### Response body (example)

```json theme={null}
{
  "data": {
    "check_id": "chk_2b89f17f008a4f7a94ef90f9",
    "partner_id": "p_xxx",
    "session_id": "sess_001",
    "decision": "deny",
    "radar_result": "banned",
    "should_hide_rate": true,
    "billable": true,
    "checked_at": "2026-02-19T23:35:46.177Z"
  },
  "message": "success"
}
```

Decision handling:

* `decision = deny`: hide the rate / stop booking flow
* `decision = allow` or `bypass`: continue booking flow

## How Correlation Works

* Snippet and check API must share the same `session-id`.
* Snippet posts browser/device/network hints first.
* Check API merges that signal set with server payload and returns one risk decision.

## Security Model (Two Keys)

* `collector-key`: browser-side, limited to signal collection endpoint.
* `api-key`: server-side, required for `POST /api/v1/radar/checks`.

Do not use `api-key` in frontend code.

## Optional: Manual Collector Test (Browser Fetch)

If you want to simulate snippet behavior:

```javascript theme={null}
fetch("https://<your-host>/api/v1/radar/sessions/signals", {
  method: "POST",
  headers: {
    "content-type": "application/json",
    "session-id": "sess_001",
    "x-brg-collector-key": "<collector-key>"
  },
  body: JSON.stringify({
    page_url: location.href,
    referrer: document.referrer,
    user_agent: navigator.userAgent,
    language: navigator.language,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    screen: {
      width: window.screen.width,
      height: window.screen.height,
      pixel_ratio: window.devicePixelRatio
    },
    device: {
      platform: navigator.platform,
      hardware_concurrency: navigator.hardwareConcurrency,
      touch_points: navigator.maxTouchPoints || 0
    },
    fingerprint: {
      visitor_id: "vis_demo_001"
    }
  })
});
```
