# Webhooks

### Overview

This document consolidates all webhook definitions, payload formats, security requirements, and delivery rules.

### Security (Signature Verification)

All webhook requests are signed by UR and must be verified by the partner. Use the rules in [Signature and Verification](/developer-resources/signature-and-verify.md).

Headers:

```
X-Api-Signature: <Hex signature with 0x prefix, signing content "{responseBody}">
X-Api-PublicKey: <Ethereum address, optional>
```

Verification steps:

1. Read the raw request body as a string.
2. Recover the signer address using the body and `X-Api-Signature`.
3. Accept the webhook only if the recovered address matches the configured UR public key.

### Payload Format

All webhook requests adopt a unified top-level structure:

```json
{
  "event": "transaction",
  "data": {},
  "timestamp": 1704234567
}
```

| Field       | Type   | Description                                        |
| ----------- | ------ | -------------------------------------------------- |
| `event`     | string | Event type (see Event Types below)                 |
| `data`      | object | Event data, structure varies based on `event` type |
| `timestamp` | int64  | Event occurrence Unix timestamp (seconds)          |

### Event Types

#### Event: transaction

When a user's transaction is confirmed on-chain, UR pushes this event.

**Request Example**:

```json
{
  "event": "transaction",
  "timestamp": 1768659501,
  "data": {
    // Follows the TransactionData structure defined in the API reference
  }
}
```

**Data Structure**: [`TransactionData`](/developer-resources/api-reference-delegated-contract-mode.md#transactiondata) (see API reference for field definitions).

#### Event: allowance

When a user sets or cancels ERC20 authorization on-chain, UR pushes this event.

**Request Example**:

```json
{
  "event": "allowance",
  "timestamp": 1704234567,
  "data": {
    "urId": 12345,
    "allowances": [
      {
        "tokenSymbol": "USD24",
        "hasAllowance": true,
        "chainId": "eip155:5000"
      }
    ]
  }
}
```

**AllowanceUpdateData Field Description**:

| Field        | Type  | Required | Description               |
| ------------ | ----- | -------- | ------------------------- |
| `urId`       | int64 | Yes      | UR user ID                |
| `allowances` | array | Yes      | Authorization status list |

**Allowance Structure**:

| Field          | Type   | Required | Description                                                   |
| -------------- | ------ | -------- | ------------------------------------------------------------- |
| `tokenSymbol`  | string | Yes      | Token symbol (USD24/EUR24/CHF24/JPY24/CNH24/SGD24/HKD24/USDC) |
| `hasAllowance` | bool   | Yes      | Whether authorization is set (true if on-chain allowance > 0) |
| `chainId`      | string | No       | Chain ID in CAIP-2 format (e.g., `eip155:5000`)               |

#### Event: sumsub\_kyc\_result

When a user completes and passes the SumSub questionnaire, UR notifies the partner.

**Request Example**:

```json
{
  "event": "sumsub_kyc_result",
  "data": {
    "tokenId": "123456",
    "kycResult": "Pass"
  },
  "timestamp": 1706173200
}
```

**Field Definitions**:

| Field       | Type   | Description                                                          |
| ----------- | ------ | -------------------------------------------------------------------- |
| `tokenId`   | string | UR ID (Token ID), the unique user identifier created during minting. |
| `kycResult` | string | Enum values: `Pass`, `Rejected`                                      |

#### Event: kyc\_status

When a user completes all KYC steps and Fiat24 returns the compliance result, UR notifies the partner.

**Request Example**:

```json
{
  "event": "kyc_status",
  "data": {
    "tokenId": "123456",
    "status": "Pass"
  },
  "timestamp": 1706173200
}
```

**Field Definitions**:

| Field     | Type   | Description                                                          |
| --------- | ------ | -------------------------------------------------------------------- |
| `tokenId` | string | UR ID (Token ID), the unique user identifier created during minting. |
| `status`  | string | Enum values: `Pending`, `Pass`, `Rejected`, `ManualReview`, `Error`  |

### Response Requirements

Partners should return HTTP 200 within 10 seconds. If a non-200 response or timeout occurs, UR will retry up to 3 times with 5-minute intervals.

### Configuration

Partners must provide:

* Webhook callback URL (HTTPS only)
* Event types to subscribe to
* Optional custom timeout or retry policy


---

# 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.ur.app/developer-resources/webhook.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.
