# Payment Errors

Payment error handling allows your host application to hook into payment failure events - for example when a user has insufficient balance - and control how the game responds. This feature is **opt-in**. To enable it, notify your THNDR integration contact.

Once enabled, the integration is **required**. When a payment fails, the game emits a `postMessage` and waits for your app to respond with an action before proceeding. If your app does not respond, the game will hang indefinitely.

### The exchange

The flow is a two-step message exchange between the game and your host application.

#### Step 1 - Game notifies your app

When a payment error occurs, the game sends:

```json
{
  "message": "operator_handle_payment_error",
  "data": {
    "error": {}
  }
}
```

The `error` object contains details about what went wrong. Your app should inspect this to decide which action to return.

#### Step 2 - Your app responds with an action

Your host application must reply to the game with `operator_payment_error_handled` and one of four actions:

```json
{
  "message": "operator_payment_error_handled",
  "data": {
    "action": "RETRY"
  }
}
```

| Action           | Behaviour                                                        |
| ---------------- | ---------------------------------------------------------------- |
| `RETRY`          | The game retries the payment automatically                       |
| `GENERIC_ERROR`  | The game displays a standard error screen                        |
| `OPERATOR_ERROR` | The game displays a custom error message defined by you          |
| `IGNORE`         | The game handles the error silently with no user-facing feedback |

If you use `OPERATOR_ERROR`, include a `message` field with the text to display:

```json
{
  "message": "operator_payment_error_handled",
  "data": {
    "action": "OPERATOR_ERROR",
    "message": "Your account has insufficient funds. Please top up to continue."
  }
}
```

### Example listener

```javascript
window.addEventListener("message", (event) => {
  // Validate origin
  if (event.origin !== "https://game.thndr-cdn.com") return;

  let msg;
  try {
    msg = JSON.parse(event.data);
  } catch (e) {
    return;
  }

  if (msg.message.endsWith("operator_handle_payment_error")) {
    const error = msg.data?.error;

    // Inspect the error and decide how to respond
    const response = {
      message: "operator_payment_error_handled",
      data: {
        action: "RETRY", // Replace with your logic
      },
    };

    const iframe = document.getElementById("thndr-iframe");
    iframe.contentWindow.postMessage(
      JSON.stringify(response),
      "https://game.thndr-cdn.com"
    );
  }
});
```


---

# Agent Instructions: 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:

```
GET https://docs.thndr.io/integration/customisation/payment-errors.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
