> For the complete documentation index, see [llms.txt](https://partner-docs.covergenius.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://partner-docs.covergenius.com/xcover-journeys/integration/messaging.md).

# Messaging

Send and receive real-time events between your app and the XCJ journey using a shared postMessage-based event contract, across Web, iOS, Android, and React Native.

### Overview

Once a journey is embedded, your app and the journey communicate over a message-passing channel: `window.postMessage` on web, or the equivalent native WebView message bridge on iOS, Android, and React Native.

{% hint style="info" %}
The **event contract (envelope shape, event names, and payloads) is identical on every platform.** Only the transport mechanics (how you send and receive the JSON) differ. Platform-specific setup lives in the installation pages; this page is the shared reference.
{% endhint %}

Use messaging to:

* React to journey lifecycle events (ready, complete, error, navigation) without polling.
* Show or hide the journey from your own UI (e.g. a "Get travel insurance" trigger button).
* Exchange offer data with the journey: request an offer, receive the offer response, and observe what the customer selects.
* Detect purchase completion and pick up the booking reference for your own records.

{% hint style="warning" %}
Messaging is for **non-PII, operational data only**. Cover Genius never sends customer personal data through this channel; PII exchange stays server to server, per [Data Exchange](/xcover-journeys/integration/data-exchange.md). The same rule applies to what you send: do not put customer PII into `CG_JOURNEY_OFFER_UPDATE.changes` or any other outbound payload.
{% endhint %}

### How it works

Every message, in both directions, is a small JSON envelope:

```json
{
  "source": "xcover-journeys",
  "type": "CG_JOURNEY_READY",
  "payload": {}
}
```

| Field     | Type                | Description                                                                            |
| --------- | ------------------- | -------------------------------------------------------------------------------------- |
| `source`  | `"xcover-journeys"` | Constant. Used to distinguish journey messages from any other traffic on your channel. |
| `type`    | `string`            | The event name. See the tables below for the full list.                                |
| `payload` | `object`            | Event-specific data. Empty object (`{}`) for events that carry no data.                |

{% hint style="warning" %}
There is currently no `version` field in the envelope. Treat `type` as the contract; new event types will be additive, and existing payload shapes will not change in a breaking way without a new `type`.
{% endhint %}

**There is no `READY`-then-request handshake requirement.**

You do not need to wait for `CG_JOURNEY_READY` before sending inbound events. The journey buffers early messages per event type (up to 10 messages, oldest dropped first once the cap is hit) and delivers them once it starts listening.

Waiting for `CG_JOURNEY_READY` first is still the simplest mental model and is recommended, but not required for correctness.

### Events reference

Event names are exact string values sent in the `type` field. They are case sensitive.

#### Outbound, journey to your app

<table data-header-hidden><thead><tr><th width="266.5"></th><th width="249"></th><th></th></tr></thead><tbody><tr><td>Event (<code>type</code>)</td><td>When it fires</td><td>Payload</td></tr><tr><td><code>CG_JOURNEY_READY</code></td><td>Once, automatically, when the journey has mounted and is ready to receive messages.</td><td><code>{}</code></td></tr><tr><td><code>CG_JOURNEY_COMPLETE</code></td><td>The journey has reached a terminal state: the customer purchased, declined, or an unrecoverable error occurred.</td><td><code>outcome: "purchased" | "declined" | "error"</code>, <code>policy_id?: string</code> (present when <code>outcome</code> is <code>"purchased"</code>)</td></tr><tr><td><code>CG_JOURNEY_ERROR</code></td><td>An error occurred inside the journey.</td><td><code>code: "API_ERROR" | "RENDER_ERROR"</code>, <code>message: string</code></td></tr><tr><td><code>CG_JOURNEY_NAVIGATE</code></td><td>The journey wants the host app to navigate (e.g. a "return to site" link inside the journey).</td><td><code>direction: "back" | "home" | "forward"</code>, <code>url?: string</code></td></tr><tr><td><code>CG_JOURNEY_OFFER_RESPONSE</code></td><td>Sent in reply to a <code>CG_JOURNEY_OFFER_REQUEST</code>, containing the offer built for the customer.</td><td><code>offer_id: string</code>, <code>currency: string</code>, <code>products: OfferResponseProduct[]</code>, each with <code>id: string</code>, <code>type: string</code>, <code>price: number | null</code>, <code>price_formatted: string | null</code></td></tr><tr><td><code>CG_JOURNEY_OFFER_SELECTION</code></td><td>The customer changed their product/option selection within the offer (before submitting).</td><td><code>selectedOption: string | undefined</code>, <code>selectedProductIDs: string[]</code>, <code>offer_id: string</code></td></tr><tr><td><code>CG_JOURNEY_PRODUCT_SELECTED</code></td><td>The customer submitted/confirmed a product selection.</td><td><code>selectedOption: string</code>, <code>selectedProductIDs: string[]</code>, <code>offer_id: string</code></td></tr><tr><td><code>CG_JOURNEY_OFFER_DECLINED</code></td><td>The customer explicitly declined the offer.</td><td><code>offer_id: string</code></td></tr><tr><td><code>CG_JOURNEY_PAYMENT</code></td><td>Payment for the offer has been taken.</td><td><code>booking_reference: string</code></td></tr></tbody></table>

#### Inbound, your app to journey

<table data-header-hidden><thead><tr><th width="269"></th><th width="249"></th><th></th></tr></thead><tbody><tr><td>Event (<code>type</code>)</td><td>Purpose</td><td>Payload</td></tr><tr><td><code>CG_JOURNEY_SHOW</code></td><td>Show the journey (if you control its visibility from your own UI).</td><td><code>{}</code></td></tr><tr><td><code>CG_JOURNEY_HIDE</code></td><td>Hide the journey.</td><td><code>{}</code></td></tr><tr><td><code>CG_JOURNEY_OFFER_REQUEST</code></td><td>Ask the journey to build/return an offer. Triggers a <code>CG_JOURNEY_OFFER_RESPONSE</code> in reply.</td><td><code>product_type?: string</code>, <code>locale?: string</code></td></tr><tr><td><code>CG_JOURNEY_OFFER_UPDATE</code></td><td>Update an existing offer in place (e.g. changed booking context).</td><td><code>offer_id: string</code>, <code>changes: Record&#x3C;string, unknown></code></td></tr><tr><td><code>CG_JOURNEY_REQUIRE_SELECTION</code></td><td>Tell the journey a product selection is mandatory before the customer can proceed.</td><td><code>offer_id: string</code></td></tr></tbody></table>

{% hint style="info" %}
`changes` in `CG_JOURNEY_OFFER_UPDATE` is an open key/value map. Confirm the exact keys your integration needs with your Cover Genius integration manager, since they are product and vertical specific.
{% endhint %}

### Errors

There is a single application-level error event, sent outbound only:

| `code`         | Meaning                                                                         | Suggested handling                                                                                                 |
| -------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `API_ERROR`    | The journey failed to complete an API call it depends on (e.g. quote, booking). | Surface a generic "something went wrong" state on your side; do not retry automatically from the host.             |
| `RENDER_ERROR` | The journey failed to render.                                                   | Treat as a fallback trigger, for example redirecting the customer to a non-embedded fallback flow if you have one. |

`message` is a human readable description intended for logging and debugging, not for displaying to customers verbatim.

{% hint style="warning" %}
There is currently no inbound error event. Your app cannot signal an error state into the journey over this channel.
{% endhint %}

#### Silent failure modes to be aware of

These do not raise an error event. They fail silently by design, so integrations should be tested against them directly:

| Situation                                                                                      | What happens                                                                                                   |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Your origin/channel is not on the journey's trusted allowlist                                  | The journey drops the message. Nothing is delivered to your listeners, and no error event is sent back to you. |
| You send a message with a malformed envelope (missing `source`/`type`, or `payload` is `null`) | The journey ignores it silently.                                                                               |
| Transport-level misconfiguration (wrong target origin on web, bridge not registered on mobile) | The message is never delivered at all. This is a platform transport behavior, not journey-specific.            |

### FAQ

**Do I need to wait for `CG_JOURNEY_READY` before sending events to the journey?**

* No. Early inbound messages are buffered and delivered once the journey starts listening. Waiting for `READY` first is simpler to reason about and still recommended, but not required.

**Is there a way to know why a message I sent wasn't received?**

* Not from your app. If your origin/channel isn't trusted, or your envelope is malformed, the message is dropped without any error sent back to you. Verify your setup with your integration manager, and check the envelope shape (`source`, `type`, `payload`) against the reference above.

**Can I send arbitrary custom events on this channel?**

* No. `type` must be one of the documented event names, and `source` must be `"xcover-journeys"`. Unrecognized types are ignored.

**Is this channel used for PII?**

* No. Keep customer personal data out of these payloads entirely; PII exchange is server to server per [Data Exchange](/xcover-journeys/integration/data-exchange.md).

**Is the protocol different on mobile?**

* No. Same envelope, same event names, same payloads. Only the transport differs; see the platform-specific installation page for how to send and receive the envelope on Web, iOS, Android, or React Native.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://partner-docs.covergenius.com/xcover-journeys/integration/messaging.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
