# Merkl API

The official API to access data related to Merkl campaigns, built and maintained by Merkl SAS. This API is provided as is, without any warranty of any kind.

---

# POST /v4/developer/keys/

_Merkl API_

Create a new API key. The raw key is returned only once.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    }
  },
  "required": [
    "description"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    }
  },
  "required": [
    "description"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    }
  },
  "required": [
    "description"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/developer/keys/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/developer/keys/

_Merkl API_

List all API keys for the authenticated user.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/developer/keys/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/developer/keys/usage

_Merkl API_

Get usage summary across all API keys for the authenticated user.

### Query parameters

- `days` (number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/developer/keys/usage" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/developer/keys/{id}/usage

_Merkl API_

Get detailed daily usage for a specific API key.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `days` (number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/developer/keys/{id}/usage" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PATCH /v4/developer/keys/{id}

_Merkl API_

Update description for an API key.

### Path parameters

- `id` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    }
  }
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    }
  }
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "minLength": 1,
      "maxLength": 255,
      "type": "string"
    }
  }
}
```

## Example request

```bash
curl -X PATCH "https://api.merkl.xyz//v4/developer/keys/{id}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# DELETE /v4/developer/keys/{id}

_Merkl API_

Revoke an API key.

### Path parameters

- `id` (string) _(required)_

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/developer/keys/{id}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/api-keys/validate

_Merkl API_

Validate a developer API key. Returns `{ ok: true }` on success, 401 otherwise.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/api-keys/validate" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/auth/nonce/{address}

_Merkl API_

Generate a unique nonce and message for wallet authentication.

### Path parameters

- `address` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/auth/nonce/{address}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/auth/login

_Merkl API_

Authenticate a user and set a JWT cookie for session management.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "minLength": 1,
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "signature": {
      "minLength": 1,
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the wallet",
      "type": "number"
    }
  },
  "required": [
    "address",
    "message",
    "signature"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "minLength": 1,
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "signature": {
      "minLength": 1,
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the wallet",
      "type": "number"
    }
  },
  "required": [
    "address",
    "message",
    "signature"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "minLength": 1,
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "signature": {
      "minLength": 1,
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the wallet",
      "type": "number"
    }
  },
  "required": [
    "address",
    "message",
    "signature"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/auth/login" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/auth/google/start

_Merkl API_

Start the Google OAuth flow for signing in with a Google account.

### Query parameters

- `mode` (string | string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/auth/google/start?mode=<mode>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/auth/google/callback

_Merkl API_

Complete the Google OAuth flow and create or refresh the user session.

### Query parameters

- `code` (string)
- `state` (string)
- `error` (string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/auth/google/callback" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/auth/link/wallet

_Merkl API_

Link a wallet to the current (Google) session — collapses both into one wallet identity.

### Cookie parameters

- `jwt` (string)

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "minLength": 1,
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "signature": {
      "minLength": 1,
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the wallet",
      "type": "number"
    }
  },
  "required": [
    "address",
    "message",
    "signature"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "minLength": 1,
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "signature": {
      "minLength": 1,
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the wallet",
      "type": "number"
    }
  },
  "required": [
    "address",
    "message",
    "signature"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "minLength": 1,
      "type": "string"
    },
    "message": {
      "type": "string"
    },
    "signature": {
      "minLength": 1,
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the wallet",
      "type": "number"
    }
  },
  "required": [
    "address",
    "message",
    "signature"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/auth/link/wallet" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/auth/me

_Merkl API_

Get authenticated user information including address, profile, and authentication status.

### Cookie parameters

- `jwt` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/auth/me" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# DELETE /v4/auth/revoke

_Merkl API_

Revoke the current user's JWT token and clear the session cookie.

### Cookie parameters

- `jwt` (string)

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/auth/revoke" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/block-timestamp/block

_Merkl API_

Get the closest block number to a given timestamp on a specific chain

### Query parameters

- `chainId` (number) _(required)_
- `timestamp` (number) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/block-timestamp/block?chainId=<chainId>&timestamp=<timestamp>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/block-timestamp/timestamp

_Merkl API_

Get the closest timestamp to a given block number on a specific chain

### Query parameters

- `chainId` (number) _(required)_
- `blockNumber` (number) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/block-timestamp/timestamp?chainId=<chainId>&blockNumber=<blockNumber>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/block-timestamp/bounds

_Merkl API_

Get the closest lower and upper bound blocks for a given timestamp from BlockTimestampMapping

### Query parameters

- `chainId` (number) _(required)_
- `timestamp` (number) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/block-timestamp/bounds?chainId=<chainId>&timestamp=<timestamp>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/{id}

_Merkl API_

Retrieve a campaign by its unique identifier (hash or `distributionChain-campaignId` format) in the `id` path parameter.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `showPrivate` (boolean)

## Responses

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/{id}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/campaigns/generate-payload

_Merkl API_

Generate an on-chain transaction payload for creating one or more campaigns from the provided data.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "creatorAddress": {
      "type": "string"
    },
    "rewardToken": {
      "type": "string"
    },
    "distributionChainId": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "startTimestamp": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "endTimestamp": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "campaignsParams": {
      "type": "object",
      "patternProperties": {
        "^(.*)$": {
          "type": "array",
          "items": {
            "additionalProperties": true,
            "type": "object",
            "properties": {
              "amount": {
                "type": "RegExp",
                "source": "[0-9]+",
                "flags": ""
              }
            },
            "required": [
              "amount"
            ]
          }
        }
      }
    }
  },
  "required": [
    "creatorAddress",
    "rewardToken",
    "distributionChainId",
    "startTimestamp",
    "endTimestamp",
    "campaignsParams"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "creatorAddress": {
      "type": "string"
    },
    "rewardToken": {
      "type": "string"
    },
    "distributionChainId": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "startTimestamp": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "endTimestamp": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "campaignsParams": {
      "type": "object",
      "patternProperties": {
        "^(.*)$": {
          "type": "array",
          "items": {
            "additionalProperties": true,
            "type": "object",
            "properties": {
              "amount": {
                "type": "RegExp",
                "source": "[0-9]+",
                "flags": ""
              }
            },
            "required": [
              "amount"
            ]
          }
        }
      }
    }
  },
  "required": [
    "creatorAddress",
    "rewardToken",
    "distributionChainId",
    "startTimestamp",
    "endTimestamp",
    "campaignsParams"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "creatorAddress": {
      "type": "string"
    },
    "rewardToken": {
      "type": "string"
    },
    "distributionChainId": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "startTimestamp": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "endTimestamp": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "campaignsParams": {
      "type": "object",
      "patternProperties": {
        "^(.*)$": {
          "type": "array",
          "items": {
            "additionalProperties": true,
            "type": "object",
            "properties": {
              "amount": {
                "type": "RegExp",
                "source": "[0-9]+",
                "flags": ""
              }
            },
            "required": [
              "amount"
            ]
          }
        }
      }
    }
  },
  "required": [
    "creatorAddress",
    "rewardToken",
    "distributionChainId",
    "startTimestamp",
    "endTimestamp",
    "campaignsParams"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/campaigns/generate-payload" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/campaigns/{id}/metrics

_Merkl API_

Get historical metrics (TVL, APR, daily rewards) for a campaign, with pagination options.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `tvl` (object)
- `apr` (object)
- `dailyRewards` (object)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/{id}/metrics" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/{id}/storing-ids

_Merkl API_

Get the storingId(s) backing a campaign as a tree. The root node's `storingIds` belong to the campaign itself, and its `subCampaigns` array recursively lists every sub-campaign. The same storingId may appear in more than one node. Stateless campaigns return an empty `storingIds` array.

### Path parameters

- `id` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/{id}/storing-ids" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/{id}/linked

_Merkl API_

Get every opportunity linked to a campaign — its full chain of parent campaigns up to the root, plus its entire sub-campaign subtree — as a flat list of nodes. Each node carries its `campaignId` and `parentCampaignId` so you can reconstruct the tree at any depth. `self` identifies the requested campaign.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `test` (boolean)
- `point` (boolean)
- `tokenTypes` (array)
- `campaigns` (boolean)
- `excludeSubCampaigns` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/{id}/linked" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/tx

_Merkl API_

> Get campaign IDs from a creation transaction hash

Retrieve the campaign ID(s) created by a given campaign-creation transaction hash.

### Query parameters

- `hash` (string) _(required)_
- `chainId` (string | number) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/tx?hash=<hash>&chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/

_Merkl API_

Search for campaigns matching the criteria provided through query parameters.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `id` (string)
- `creatorTag` (string)
- `creatorAddress` (string)
- `creatorAddresses` (array)
- `creatorId` (string)
- `chainId` (string | number)
- `search` (string)
- `distributionChainIds` (array)
- `type` (string)
- `types` (array)
- `subType` (number)
- `campaignId` (string)
- `campaignIds` (array)
- `mainParameter` (string)
- `tokenSymbol` (string)
- `tokenAddress` (string)
- `test` (boolean)
- `tokenTypes` (array)
- `point` (boolean)
- `opportunityId` (string)
- `opportunityIds` (array)
- `status` (RegExp)
- `startTimestamp` (string)
- `endTimestamp` (string)
- `withOpportunity` (boolean)
- `distributionTypes` (array)
- `createdAfter` (Date | string | string | number | null)
- `createdBefore` (Date | string | string | number | null)
- `excludeSubCampaigns` (boolean)
- `onlySubCampaigns` (boolean)
- `rootCampaignId` (string)
- `parentCampaignId` (string)
- `mainProtocolId` (string)
- `pauseCompute` (string)
- `showPrivate` (boolean)
- `listOwner` (string)
- `campaignLists` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/count

_Merkl API_

Count the campaigns matching the filters provided through query parameters.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `id` (string)
- `creatorTag` (string)
- `creatorAddress` (string)
- `creatorAddresses` (array)
- `creatorId` (string)
- `chainId` (string | number)
- `search` (string)
- `distributionChainIds` (array)
- `type` (string)
- `types` (array)
- `subType` (number)
- `campaignId` (string)
- `campaignIds` (array)
- `mainParameter` (string)
- `tokenSymbol` (string)
- `tokenAddress` (string)
- `test` (boolean)
- `tokenTypes` (array)
- `point` (boolean)
- `opportunityId` (string)
- `opportunityIds` (array)
- `status` (RegExp)
- `startTimestamp` (string)
- `endTimestamp` (string)
- `withOpportunity` (boolean)
- `distributionTypes` (array)
- `createdAfter` (Date | string | string | number | null)
- `createdBefore` (Date | string | string | number | null)
- `excludeSubCampaigns` (boolean)
- `onlySubCampaigns` (boolean)
- `rootCampaignId` (string)
- `parentCampaignId` (string)
- `mainProtocolId` (string)
- `pauseCompute` (string)
- `showPrivate` (boolean)
- `listOwner` (string)
- `campaignLists` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaigns/aggregate

_Merkl API_

Aggregate all campaigns matching the provided filters and return a per-token breakdown of total amounts and USD values. Useful for analyzing program-level reward distribution (e.g. all rewards on a chain, all UNI rewards, or all campaigns by a creator).

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `id` (string)
- `creatorTag` (string)
- `creatorAddress` (string)
- `creatorAddresses` (array)
- `creatorId` (string)
- `chainId` (string | number)
- `search` (string)
- `distributionChainIds` (array)
- `type` (string)
- `types` (array)
- `subType` (number)
- `campaignId` (string)
- `campaignIds` (array)
- `mainParameter` (string)
- `tokenSymbol` (string)
- `tokenAddress` (string)
- `test` (boolean)
- `tokenTypes` (array)
- `point` (boolean)
- `opportunityId` (string)
- `opportunityIds` (array)
- `status` (RegExp)
- `startTimestamp` (string)
- `endTimestamp` (string)
- `withOpportunity` (boolean)
- `distributionTypes` (array)
- `createdAfter` (Date | string | string | number | null)
- `createdBefore` (Date | string | string | number | null)
- `excludeSubCampaigns` (boolean)
- `onlySubCampaigns` (boolean)
- `rootCampaignId` (string)
- `parentCampaignId` (string)
- `mainProtocolId` (string)
- `pauseCompute` (string)
- `showPrivate` (boolean)
- `listOwner` (string)
- `campaignLists` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/aggregate" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaign-lists/{owner}

_Merkl API_

List every named campaign list owned by an address, with its size and last-updated timestamp.

### Path parameters

- `owner` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaign-lists/{owner}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/campaign-lists/{owner}/{name}

_Merkl API_

Get the campaign IDs in a single named list. Returns 404 if the list does not exist.

### Path parameters

- `owner` (string) _(required)_
- `name` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaign-lists/{owner}/{name}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PUT /v4/campaign-lists/{owner}/{name}

_Merkl API_

Replace the campaign IDs in a named list (an empty array deletes the list). Requires the owner's JWT or API key.

### Path parameters

- `owner` (string) _(required)_
- `name` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X PUT "https://api.merkl.xyz//v4/campaign-lists/{owner}/{name}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# DELETE /v4/campaign-lists/{owner}/{name}

_Merkl API_

Delete a named list entirely. Requires the owner's JWT or API key. No-op if the list does not exist.

### Path parameters

- `owner` (string) _(required)_
- `name` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/campaign-lists/{owner}/{name}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/campaign-lists/{owner}/{name}/add

_Merkl API_

Append campaign IDs to a list, creating it if it does not exist. Requires the owner's JWT or API key.

### Path parameters

- `owner` (string) _(required)_
- `name` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/campaign-lists/{owner}/{name}/add" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/campaign-lists/{owner}/{name}/remove

_Merkl API_

Remove the provided campaign IDs from a list. If the list becomes empty, it is deleted. Requires the owner's JWT or API key.

### Path parameters

- `owner` (string) _(required)_
- `name` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "campaignIds": {
      "description": "Campaign IDs to include in the list. Each entry is either an internal hash (`Campaign.id`) or a `{ distributionChain, campaignId }` composite.",
      "type": "array",
      "items": {
        "anyOf": [
          {
            "minLength": 1,
            "description": "Internal campaign ID (hash string)",
            "type": "string"
          },
          {
            "description": "Composite identifier `{ distributionChain, campaignId }`",
            "type": "object",
            "properties": {
              "distributionChain": {
                "description": "Distribution chain ID",
                "type": "number"
              },
              "campaignId": {
                "minLength": 1,
                "description": "Onchain campaign ID",
                "type": "string"
              }
            },
            "required": [
              "distributionChain",
              "campaignId"
            ]
          }
        ]
      }
    }
  },
  "required": [
    "campaignIds"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/campaign-lists/{owner}/{name}/remove" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/chains/

_Merkl API_

List chains supported and integrated by Merkl. Use query parameters to filter by test chains or other criteria.

### Query parameters

- `name` (string)
- `test` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/chains/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/chains/{chainId}

_Merkl API_

Get a specific chain by its chainId path parameter

### Path parameters

- `chainId` (string | number) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/chains/{chainId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/claims/

_Merkl API_

Fetch claims filtered by chainId(s), recipient, campaignId, token, root, exact `reason`, and an inclusive `[fromTimestamp, toTimestamp]` range (Unix seconds). Scope by timestamp to keep responses light for recipients with many claims. Returns the 100 most recent claims unless a `recipient` is given, in which case all matching claims are returned.

### Query parameters

- `chainId` (string | number)
- `chainIds` (array)
- `recipient` (string)
- `campaignId` (string)
- `token` (string)
- `root` (string)
- `reason` (string)
- `fromTimestamp` (string | number)
- `toTimestamp` (string | number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/claims/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/claims/history/{address}

_Merkl API_

Fetch a recipient's historical claims, grouped per claim transaction with amounts aggregated by token.

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainIds` (array)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/claims/history/{address}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/claims/earnings/{address}

_Merkl API_

Aggregate a recipient's claimed rewards into time buckets broken down by token, in USD. Supports `bucket` granularity (day/week/month, default week) and `range` window (7d/30d/all, default all).

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainIds` (array)
- `bucket` (string | string | string)
- `range` (string | string | string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/claims/earnings/{address}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/claims/count

_Merkl API_

Returns the total number of unique claimers on a specific chain.

### Query parameters

- `chainId` (string | number) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/claims/count?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/claims/count/total

_Merkl API_

Returns the total number of unique claimers across all chains.

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/claims/count/total" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/config/{id}

_Merkl API_

Beta feature (not production ready yet) - Fetch the configuration for a specific campaign by its ID. Use id path parameter.

### Path parameters

- `id` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/config/{id}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/config/diff

_Merkl API_

Compute the diff between two config schemas. Returns an array of edit operations (insert/update/delete).

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "oldConfig": {
      "description": "The original campaign configuration."
    },
    "newConfig": {
      "description": "The new campaign configuration to compare against."
    }
  },
  "required": [
    "oldConfig",
    "newConfig"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "oldConfig": {
      "description": "The original campaign configuration."
    },
    "newConfig": {
      "description": "The new campaign configuration to compare against."
    }
  },
  "required": [
    "oldConfig",
    "newConfig"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "oldConfig": {
      "description": "The original campaign configuration."
    },
    "newConfig": {
      "description": "The new campaign configuration to compare against."
    }
  },
  "required": [
    "oldConfig",
    "newConfig"
  ]
}
```

## Responses

- **200** Override value as JSON

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/diff" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/diff/{id}

_Merkl API_

Compute the diff between the current config of a campaign and a new one. Returns an array of edit operations (insert/update/delete).

### Path parameters

- `id` (string) _(required)_

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Responses

- **200** Override value as JSON

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/diff/{id}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/extend

_Merkl API_

Beta feature (not production ready yet) - Extends a campaign configuration with the values resolved by the engine.

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/extend" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/opportunity

_Merkl API_

Beta feature (not production ready yet) - Computes an opportunity from a campaign configuration

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/opportunity" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/tvl

_Merkl API_

Beta feature (not production ready yet) - Computes a TVL from a campaign configuration

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/tvl" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/encode

_Merkl API_

Beta feature (not production ready yet) - Encodes campaign parameters into the transaction payload used to create the campaign on-chain.

### Query parameters

- `extend` (boolean)
- `signerAddress` (string)

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/encode" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/encode/override

_Merkl API_

Beta feature (not production ready yet) - Builds the transaction payload used to override (or cancel) an existing campaign on-chain, from pre-encoded on-chain args. Requires campaignId and distributionChainId query parameters.

### Query parameters

- `campaignId` (string) _(required)_
- `distributionChainId` (string | number) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "campaignId": {
      "type": "string"
    },
    "creator": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "rewardToken": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "campaignType": {
      "type": "integer"
    },
    "startTimestamp": {
      "$id": "timestamp",
      "title": "Timestamp",
      "description": "Unix timestamp in seconds (not milliseconds).",
      "type": "number"
    },
    "duration": {
      "type": "integer"
    },
    "campaignData": {
      "type": "string"
    }
  },
  "required": [
    "campaignId",
    "creator",
    "rewardToken",
    "amount",
    "campaignType",
    "startTimestamp",
    "duration",
    "campaignData"
  ],
  "description": "The new on-chain campaign parameters to apply (immutable fields preserved on-chain)."
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "campaignId": {
      "type": "string"
    },
    "creator": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "rewardToken": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "campaignType": {
      "type": "integer"
    },
    "startTimestamp": {
      "$id": "timestamp",
      "title": "Timestamp",
      "description": "Unix timestamp in seconds (not milliseconds).",
      "type": "number"
    },
    "duration": {
      "type": "integer"
    },
    "campaignData": {
      "type": "string"
    }
  },
  "required": [
    "campaignId",
    "creator",
    "rewardToken",
    "amount",
    "campaignType",
    "startTimestamp",
    "duration",
    "campaignData"
  ],
  "description": "The new on-chain campaign parameters to apply (immutable fields preserved on-chain)."
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "campaignId": {
      "type": "string"
    },
    "creator": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "rewardToken": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "campaignType": {
      "type": "integer"
    },
    "startTimestamp": {
      "$id": "timestamp",
      "title": "Timestamp",
      "description": "Unix timestamp in seconds (not milliseconds).",
      "type": "number"
    },
    "duration": {
      "type": "integer"
    },
    "campaignData": {
      "type": "string"
    }
  },
  "required": [
    "campaignId",
    "creator",
    "rewardToken",
    "amount",
    "campaignType",
    "startTimestamp",
    "duration",
    "campaignData"
  ],
  "description": "The new on-chain campaign parameters to apply (immutable fields preserved on-chain)."
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/encode/override?campaignId=<campaignId>&distributionChainId=<distributionChainId>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/encode/reallocate

_Merkl API_

Beta feature (not production ready yet) - Builds the transaction payload used to reallocate an existing campaign's unclaimed rewards on-chain (EVM calldata / Stellar XDR). Requires campaignId and distributionChainId query parameters.

### Query parameters

- `campaignId` (string) _(required)_
- `distributionChainId` (string | number) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "froms": {
      "description": "Source addresses to reallocate from (the zero address alone reallocates every wallet).",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "to": {
      "description": "Destination address that receives the reallocated rewards.",
      "type": "string"
    },
    "caller": {
      "description": "Address signing the reallocation (creator or authorized operator). Required on Stellar (transaction source), ignored on EVM.",
      "type": "string"
    }
  },
  "required": [
    "froms",
    "to"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "froms": {
      "description": "Source addresses to reallocate from (the zero address alone reallocates every wallet).",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "to": {
      "description": "Destination address that receives the reallocated rewards.",
      "type": "string"
    },
    "caller": {
      "description": "Address signing the reallocation (creator or authorized operator). Required on Stellar (transaction source), ignored on EVM.",
      "type": "string"
    }
  },
  "required": [
    "froms",
    "to"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "froms": {
      "description": "Source addresses to reallocate from (the zero address alone reallocates every wallet).",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "to": {
      "description": "Destination address that receives the reallocated rewards.",
      "type": "string"
    },
    "caller": {
      "description": "Address signing the reallocation (creator or authorized operator). Required on Stellar (transaction source), ignored on EVM.",
      "type": "string"
    }
  },
  "required": [
    "froms",
    "to"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/encode/reallocate?campaignId=<campaignId>&distributionChainId=<distributionChainId>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/encode/safe

_Merkl API_

Beta feature (not production ready yet) - Encodes campaign config to Safe transaction payload. Use ?extend=true to validate config extension before encoding.

### Query parameters

- `extend` (boolean)
- `signerAddress` (string)

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/encode/safe" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/encode/batch

_Merkl API_

Beta feature (not production ready yet) - Encodes a batch of campaign parameters into transaction payloads.

### Query parameters

- `extend` (boolean)
- `signerAddress` (string)

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/encode/batch" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/encode/batch/safe

_Merkl API_

Beta feature (not production ready yet) - Encodes batch campaign configs to Safe transaction payload. Use ?extend=true to validate config extension before encoding.

### Query parameters

- `extend` (boolean)
- `signerAddress` (string)

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/encode/batch/safe" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/config/decode/onchain/{distributionChainId}/{campaignId}

_Merkl API_

Decodes an on-chain campaign configuration. Use distributionChainId and campaignId path parameters.

### Path parameters

- `distributionChainId` (string | number) _(required)_
- `campaignId` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/config/decode/onchain/{distributionChainId}/{campaignId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/config/decode/{distributionChainId}

_Merkl API_

Decodes campaign data from the Distribution contract. Use distributionChainId path parameter and provide on-chain campaign data in body.

### Path parameters

- `distributionChainId` (string | number) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "campaignId": {
      "type": "string"
    },
    "creator": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "rewardToken": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "campaignType": {
      "type": "integer"
    },
    "startTimestamp": {
      "$id": "timestamp",
      "title": "Timestamp",
      "description": "Unix timestamp in seconds (not milliseconds).",
      "type": "number"
    },
    "duration": {
      "type": "integer"
    },
    "campaignData": {
      "type": "string"
    }
  },
  "required": [
    "campaignId",
    "creator",
    "rewardToken",
    "amount",
    "campaignType",
    "startTimestamp",
    "duration",
    "campaignData"
  ],
  "description": "On-chain campaign data fetched from the Distribution contract"
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "campaignId": {
      "type": "string"
    },
    "creator": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "rewardToken": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "campaignType": {
      "type": "integer"
    },
    "startTimestamp": {
      "$id": "timestamp",
      "title": "Timestamp",
      "description": "Unix timestamp in seconds (not milliseconds).",
      "type": "number"
    },
    "duration": {
      "type": "integer"
    },
    "campaignData": {
      "type": "string"
    }
  },
  "required": [
    "campaignId",
    "creator",
    "rewardToken",
    "amount",
    "campaignType",
    "startTimestamp",
    "duration",
    "campaignData"
  ],
  "description": "On-chain campaign data fetched from the Distribution contract"
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "campaignId": {
      "type": "string"
    },
    "creator": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "rewardToken": {
      "$id": "address",
      "title": "Address",
      "description": "Address",
      "pattern": "^(0x[a-fA-F0-9]{40}|[1-9A-HJ-NP-Za-km-z]{32,44}|[CG][A-Z0-9]{55})$",
      "type": "string"
    },
    "amount": {
      "type": "string"
    },
    "campaignType": {
      "type": "integer"
    },
    "startTimestamp": {
      "$id": "timestamp",
      "title": "Timestamp",
      "description": "Unix timestamp in seconds (not milliseconds).",
      "type": "number"
    },
    "duration": {
      "type": "integer"
    },
    "campaignData": {
      "type": "string"
    }
  },
  "required": [
    "campaignId",
    "creator",
    "rewardToken",
    "amount",
    "campaignType",
    "startTimestamp",
    "duration",
    "campaignData"
  ],
  "description": "On-chain campaign data fetched from the Distribution contract"
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/decode/{distributionChainId}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/config/decode/{distributionChainId}/{payload}

_Merkl API_

Decodes campaign from a raw payload. Use distributionChainId and payload (hex string) path parameters.

### Path parameters

- `distributionChainId` (string | number) _(required)_
- `payload` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/config/decode/{distributionChainId}/{payload}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/config/decode/safe

_Merkl API_

Decodes a Safe transaction payload back to the original campaign configurations. Returns an array of configs.

## Request body

**`application/json`**
```json
{
  "description": "Safe payload containing campaign creation transactions"
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "description": "Safe payload containing campaign creation transactions"
}
```
**`multipart/form-data`**
```json
{
  "description": "Safe payload containing campaign creation transactions"
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/decode/safe" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/decode/args/createCampaign

_Merkl API_

Decodes arguments of the create campaign function back to the original campaign configuration.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "distributionChainId": {
      "description": "Chain ID where the campaign is being created",
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "description": "Chain ID where the campaign is being created",
          "type": "number"
        }
      ]
    },
    "args": {
      "description": "Arguments of the call to the createCampaign function"
    }
  },
  "required": [
    "distributionChainId",
    "args"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "distributionChainId": {
      "description": "Chain ID where the campaign is being created",
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "description": "Chain ID where the campaign is being created",
          "type": "number"
        }
      ]
    },
    "args": {
      "description": "Arguments of the call to the createCampaign function"
    }
  },
  "required": [
    "distributionChainId",
    "args"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "distributionChainId": {
      "description": "Chain ID where the campaign is being created",
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "description": "Chain ID where the campaign is being created",
          "type": "number"
        }
      ]
    },
    "args": {
      "description": "Arguments of the call to the createCampaign function"
    }
  },
  "required": [
    "distributionChainId",
    "args"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/decode/args/createCampaign" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/config/store

_Merkl API_

Stores campaign configurations keyed by their hash. Provide the campaign configuration payload in the request body.

## Request body

**`application/json`**
```json
{}
```
**`application/x-www-form-urlencoded`**
```json
{}
```
**`multipart/form-data`**
```json
{}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/config/store" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/config/hash/{hash}

_Merkl API_

Gets a campaign configuration by its hash. If campaignId and distributionChainId are provided, associates the configuration with that campaign.

### Path parameters

- `hash` (string) _(required)_

### Query parameters

- `campaignId` (string)
- `distributionChainId` (string | number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/config/hash/{hash}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PUT /v4/key-value-stores/{key}/entries

_Merkl API_

Upsert a single entry. Authenticate with a JWT for user access, or an X-API-Key header for service access.

### Path parameters

- `key` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "pattern": "^0x[a-fA-F0-9]{40}$|^0x[a-fA-F0-9]{64}$",
      "description": "Target Ethereum address (or bytes32 campaignId for APR configs)",
      "type": "string"
    },
    "value": {
      "maxLength": 1024,
      "description": "JSON value (shape gated by config type)",
      "type": "string"
    }
  },
  "required": [
    "address",
    "value"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "pattern": "^0x[a-fA-F0-9]{40}$|^0x[a-fA-F0-9]{64}$",
      "description": "Target Ethereum address (or bytes32 campaignId for APR configs)",
      "type": "string"
    },
    "value": {
      "maxLength": 1024,
      "description": "JSON value (shape gated by config type)",
      "type": "string"
    }
  },
  "required": [
    "address",
    "value"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "pattern": "^0x[a-fA-F0-9]{40}$|^0x[a-fA-F0-9]{64}$",
      "description": "Target Ethereum address (or bytes32 campaignId for APR configs)",
      "type": "string"
    },
    "value": {
      "maxLength": 1024,
      "description": "JSON value (shape gated by config type)",
      "type": "string"
    }
  },
  "required": [
    "address",
    "value"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X PUT "https://api.merkl.xyz//v4/key-value-stores/{key}/entries" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/key-value-stores/{key}/entries

_Merkl API_

List entries. Public for stores configured as publicly readable; otherwise requires authentication.

### Path parameters

- `key` (string) _(required)_

### Query parameters

- `page` (string | number)
- `pageSize` (string | number)
- `value` (string)

### Header parameters

- `page` (string | number)
- `pageSize` (string | number)
- `value` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/key-value-stores/{key}/entries" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "page: <page>" \
  -H "pageSize: <pageSize>" \
  -H "value: <value>"
```

---

# PUT /v4/key-value-stores/{key}/entries/batch

_Merkl API_

Batch upsert entries. Requires X-API-Key authentication.

### Path parameters

- `key` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "entries": {
      "minItems": 1,
      "maxItems": 1000,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "address": {
            "pattern": "^0x[a-fA-F0-9]{40}$|^0x[a-fA-F0-9]{64}$",
            "type": "string"
          },
          "value": {
            "maxLength": 1024,
            "type": "string"
          }
        },
        "required": [
          "address",
          "value"
        ]
      }
    }
  },
  "required": [
    "entries"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "entries": {
      "minItems": 1,
      "maxItems": 1000,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "address": {
            "pattern": "^0x[a-fA-F0-9]{40}$|^0x[a-fA-F0-9]{64}$",
            "type": "string"
          },
          "value": {
            "maxLength": 1024,
            "type": "string"
          }
        },
        "required": [
          "address",
          "value"
        ]
      }
    }
  },
  "required": [
    "entries"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "entries": {
      "minItems": 1,
      "maxItems": 1000,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "address": {
            "pattern": "^0x[a-fA-F0-9]{40}$|^0x[a-fA-F0-9]{64}$",
            "type": "string"
          },
          "value": {
            "maxLength": 1024,
            "type": "string"
          }
        },
        "required": [
          "address",
          "value"
        ]
      }
    }
  },
  "required": [
    "entries"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X PUT "https://api.merkl.xyz//v4/key-value-stores/{key}/entries/batch" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/key-value-stores/{key}/entries/{address}

_Merkl API_

Get a single entry by address

### Path parameters

- `key` (string) _(required)_
- `address` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/key-value-stores/{key}/entries/{address}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# DELETE /v4/key-value-stores/{key}/entries/{address}

_Merkl API_

Delete an entry. Users may delete their own entry; the store owner or an X-API-Key holder may delete any entry.

### Path parameters

- `key` (string) _(required)_
- `address` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/key-value-stores/{key}/entries/{address}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/key-value-stores/self

_Merkl API_

Create a key-value store you own (allowlisted users, X-API-Key). `key` is a suffix; the response returns the canonical, owner-namespaced key used for entry writes, update and delete.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "key": {
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Unique human-readable key (alphanumeric, hyphens, underscores). Server-namespaced per owner.",
      "type": "string"
    },
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "type": {
      "description": "Semantic type — determines the required JSON shape of entry values",
      "anyOf": [
        {
          "const": "WHITELIST",
          "type": "string"
        },
        {
          "const": "BLACKLIST",
          "type": "string"
        },
        {
          "const": "BOOST",
          "type": "string"
        },
        {
          "const": "REFERRER",
          "type": "string"
        },
        {
          "const": "FORWARDER",
          "type": "string"
        },
        {
          "const": "APR",
          "type": "string"
        }
      ]
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "description": "Capped at the caller's quota",
      "type": "number"
    },
    "publicRead": {
      "default": true,
      "type": "boolean"
    }
  },
  "required": [
    "key",
    "type"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "key": {
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Unique human-readable key (alphanumeric, hyphens, underscores). Server-namespaced per owner.",
      "type": "string"
    },
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "type": {
      "description": "Semantic type — determines the required JSON shape of entry values",
      "anyOf": [
        {
          "const": "WHITELIST",
          "type": "string"
        },
        {
          "const": "BLACKLIST",
          "type": "string"
        },
        {
          "const": "BOOST",
          "type": "string"
        },
        {
          "const": "REFERRER",
          "type": "string"
        },
        {
          "const": "FORWARDER",
          "type": "string"
        },
        {
          "const": "APR",
          "type": "string"
        }
      ]
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "description": "Capped at the caller's quota",
      "type": "number"
    },
    "publicRead": {
      "default": true,
      "type": "boolean"
    }
  },
  "required": [
    "key",
    "type"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "key": {
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Unique human-readable key (alphanumeric, hyphens, underscores). Server-namespaced per owner.",
      "type": "string"
    },
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "type": {
      "description": "Semantic type — determines the required JSON shape of entry values",
      "anyOf": [
        {
          "const": "WHITELIST",
          "type": "string"
        },
        {
          "const": "BLACKLIST",
          "type": "string"
        },
        {
          "const": "BOOST",
          "type": "string"
        },
        {
          "const": "REFERRER",
          "type": "string"
        },
        {
          "const": "FORWARDER",
          "type": "string"
        },
        {
          "const": "APR",
          "type": "string"
        }
      ]
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "description": "Capped at the caller's quota",
      "type": "number"
    },
    "publicRead": {
      "default": true,
      "type": "boolean"
    }
  },
  "required": [
    "key",
    "type"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/key-value-stores/self" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/key-value-stores/self

_Merkl API_

List the key-value stores you own (X-API-Key)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/key-value-stores/self" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PATCH /v4/key-value-stores/self/{key}

_Merkl API_

Update a key-value store you own by its canonical key (X-API-Key)

### Path parameters

- `key` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "publicRead": {
      "type": "boolean"
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    }
  }
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "publicRead": {
      "type": "boolean"
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    }
  }
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "publicRead": {
      "type": "boolean"
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    }
  }
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X PATCH "https://api.merkl.xyz//v4/key-value-stores/self/{key}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# DELETE /v4/key-value-stores/self/{key}

_Merkl API_

Delete a key-value store you own (by canonical key) and all its entries (X-API-Key)

### Path parameters

- `key` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/key-value-stores/self/{key}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/

_Merkl API_

Retrieves all creators matching the provided query filters

### Query parameters

- `id` (string)
- `address` (string)
- `search` (string)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}

_Merkl API_

Retrieves a specific creator by their ID or slug

### Path parameters

- `creator` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}/dashboard

_Merkl API_

Returns dashboard metrics and overview for a specific creator

### Path parameters

- `creator` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}/dashboard" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}/opportunities/count

_Merkl API_

Returns the total count of opportunities for a specific creator

### Path parameters

- `creator` (string) _(required)_

### Query parameters

- `name` (string)
- `search` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `type` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `explorerAddress` (string)
- `campaignTypes` (RegExp)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}/opportunities/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}/opportunities

_Merkl API_

Returns paginated opportunities for a specific creator. Use page, items, and other query parameters to filter.

### Path parameters

- `creator` (string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `type` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `explorerAddress` (string)
- `campaignTypes` (RegExp)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}/opportunities" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}/campaigns

_Merkl API_

Returns all campaigns for a specific creator. Filter by status query parameter.

### Path parameters

- `creator` (string) _(required)_

### Query parameters

- `status` (string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}/campaigns" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/campaigns/{campaignId}

_Merkl API_

Returns campaign metrics for a specific campaign. Use campaignId path parameter and pagination query parameters.

### Path parameters

- `campaignId` (string) _(required)_

### Query parameters

- `tvl` (object)
- `apr` (object)
- `dailyRewards` (object)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/campaigns/{campaignId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}/opportunity/{opportunityId}/metrics

_Merkl API_

Returns opportunity metrics for a specific creator and opportunity combination

### Path parameters

- `creator` (string) _(required)_
- `opportunityId` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}/opportunity/{opportunityId}/metrics" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/creators/{creator}/distributed/over-time

_Merkl API_

Token distribution over time for a creator, bucketed and broken down per reward token (token amounts, not USD)

### Path parameters

- `creator` (string) _(required)_

### Query parameters

- `range` (string | string | string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/creators/{creator}/distributed/over-time" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/credits/pricing

_Merkl API_

Get points-campaign billing pricing constants (USD)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/pricing" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/credits/estimate

_Merkl API_

Estimate the credit cost of a points campaign's next run, mirroring the engine pre-check. Returns `estimatedCost` (pro-rated over the next run window, capped at 1 week) and `threshold` (= max(estimatedCost, BASE_COST_PER_WEEK), the minimum balance required for the pre-check to pass).

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "startTimestamp": {
      "description": "Campaign start timestamp (unix seconds)",
      "type": "number"
    },
    "endTimestamp": {
      "description": "Campaign end timestamp (unix seconds)",
      "type": "number"
    },
    "computedUntil": {
      "description": "Last computed-until timestamp (unix seconds). Defaults to startTimestamp.",
      "type": "number"
    },
    "recipientCount": {
      "minimum": 0,
      "description": "Expected recipient count",
      "type": "number"
    }
  },
  "required": [
    "startTimestamp",
    "endTimestamp"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "startTimestamp": {
      "description": "Campaign start timestamp (unix seconds)",
      "type": "number"
    },
    "endTimestamp": {
      "description": "Campaign end timestamp (unix seconds)",
      "type": "number"
    },
    "computedUntil": {
      "description": "Last computed-until timestamp (unix seconds). Defaults to startTimestamp.",
      "type": "number"
    },
    "recipientCount": {
      "minimum": 0,
      "description": "Expected recipient count",
      "type": "number"
    }
  },
  "required": [
    "startTimestamp",
    "endTimestamp"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "startTimestamp": {
      "description": "Campaign start timestamp (unix seconds)",
      "type": "number"
    },
    "endTimestamp": {
      "description": "Campaign end timestamp (unix seconds)",
      "type": "number"
    },
    "computedUntil": {
      "description": "Last computed-until timestamp (unix seconds). Defaults to startTimestamp.",
      "type": "number"
    },
    "recipientCount": {
      "minimum": 0,
      "description": "Expected recipient count",
      "type": "number"
    }
  },
  "required": [
    "startTimestamp",
    "endTimestamp"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/credits/estimate" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/credits/estimate/total

_Merkl API_

Estimate the total credit cost of a points campaign over its full duration (endTimestamp − startTimestamp). Used at creation time to gate campaign submission when the creator's balance is insufficient. Returns `estimatedCost` (full pro-rated cost) and `threshold` (= max(estimatedCost, BASE_COST_PER_WEEK)).

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "startTimestamp": {
      "description": "Campaign start timestamp (unix seconds)",
      "type": "number"
    },
    "endTimestamp": {
      "description": "Campaign end timestamp (unix seconds)",
      "type": "number"
    },
    "computedUntil": {
      "description": "Last computed-until timestamp (unix seconds). Defaults to startTimestamp.",
      "type": "number"
    },
    "recipientCount": {
      "minimum": 0,
      "description": "Expected recipient count",
      "type": "number"
    }
  },
  "required": [
    "startTimestamp",
    "endTimestamp"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "startTimestamp": {
      "description": "Campaign start timestamp (unix seconds)",
      "type": "number"
    },
    "endTimestamp": {
      "description": "Campaign end timestamp (unix seconds)",
      "type": "number"
    },
    "computedUntil": {
      "description": "Last computed-until timestamp (unix seconds). Defaults to startTimestamp.",
      "type": "number"
    },
    "recipientCount": {
      "minimum": 0,
      "description": "Expected recipient count",
      "type": "number"
    }
  },
  "required": [
    "startTimestamp",
    "endTimestamp"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "startTimestamp": {
      "description": "Campaign start timestamp (unix seconds)",
      "type": "number"
    },
    "endTimestamp": {
      "description": "Campaign end timestamp (unix seconds)",
      "type": "number"
    },
    "computedUntil": {
      "description": "Last computed-until timestamp (unix seconds). Defaults to startTimestamp.",
      "type": "number"
    },
    "recipientCount": {
      "minimum": 0,
      "description": "Expected recipient count",
      "type": "number"
    }
  },
  "required": [
    "startTimestamp",
    "endTimestamp"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/credits/estimate/total" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/credits/{creatorId}

_Merkl API_

Get credit balance for a creator

### Path parameters

- `creatorId` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/{creatorId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/credits/{creatorId}/operations

_Merkl API_

List credit operations for a creator

### Path parameters

- `creatorId` (string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `type` (string | string)
- `category` (string | string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/{creatorId}/operations" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/credits/{creatorId}/operations/count

_Merkl API_

Get the number of credit operations for a creator, optionally filtered by type

### Path parameters

- `creatorId` (string) _(required)_

### Query parameters

- `type` (string | string)
- `category` (string | string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/{creatorId}/operations/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/credits/{creatorId}/operations/aggregate

_Merkl API_

Get the signed sum of credit operations for a creator. SUBTRACT amounts count as negative, ADD as positive.

### Path parameters

- `creatorId` (string) _(required)_

### Query parameters

- `type` (string | string)
- `category` (string | string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/{creatorId}/operations/aggregate" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/credits/{creatorId}/operations/breakdowns

_Merkl API_

Get credit operations grouped by category with signed totals. All Auto-claim labels are bucketed together. SUBTRACT amounts count as negative, ADD as positive.

### Path parameters

- `creatorId` (string) _(required)_

### Query parameters

- `type` (string | string)
- `category` (string | string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/{creatorId}/operations/breakdowns" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/credits/{creatorId}/paused-campaigns

_Merkl API_

Count campaigns paused due to insufficient credits for a creator

### Path parameters

- `creatorId` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/credits/{creatorId}/paused-campaigns" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/enums/

_Merkl API_

List all available enums in the system. Returns enum names, types (string/number), and metadata availability.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/enums/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/enums/{enumName}

_Merkl API_

Get detailed information about a specific enum including all entries with their values, names, and descriptions (if available).

### Path parameters

- `enumName` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/enums/{enumName}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/enums/{enumName}/convert/{value}

_Merkl API_

Convert an enum value bidirectionally. For number enums: provide a number to get its string name. For string enums: provide a string to get its value. Returns the converted value with metadata if available.

### Path parameters

- `enumName` (string) _(required)_
- `value` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/enums/{enumName}/convert/{value}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/enums/{enumName}/batch-convert

_Merkl API_

Batch convert multiple enum values at once. Accepts an array of values and returns an array of conversion results. Maximum 100 values per request.

### Path parameters

- `enumName` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "values": {
      "description": "Array of values to convert",
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "number"
          }
        ]
      }
    }
  },
  "required": [
    "values"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "values": {
      "description": "Array of values to convert",
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "number"
          }
        ]
      }
    }
  },
  "required": [
    "values"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "values": {
      "description": "Array of values to convert",
      "minItems": 1,
      "maxItems": 100,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "number"
          }
        ]
      }
    }
  },
  "required": [
    "values"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/enums/{enumName}/batch-convert" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/bucket/health/proofs

_Merkl API_

> Check for stale proof ingestion files

Always returns HTTP 200. `status` is `STALE` when any proof file is older than the staleness threshold, `OK` otherwise. Configure a keyword monitor to alert when `STALE` is present.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/bucket/health/proofs" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/bucket/health/diff

_Merkl API_

> Check for stale diff / diff-breakdown ingestion files

Always returns HTTP 200. `status` is `STALE` when any diff / diff-breakdown file is older than the staleness threshold, `OK` otherwise. Configure a keyword monitor to alert when `STALE` is present.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/bucket/health/diff" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/bucket/health/transactions

_Merkl API_

> Check for stale transaction and autoclaim ingestion files

Always returns HTTP 200. `status` is `STALE` when any transaction and autoclaim file is older than the staleness threshold, `OK` otherwise. Configure a keyword monitor to alert when `STALE` is present.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/bucket/health/transactions" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/redis/health

_Merkl API_

> Check monitored Redis caches for staleness

Always returns HTTP 200. `status` is `STALE` when any monitored Redis cache hasn't been refreshed recently enough, `OK` otherwise. Configure a keyword monitor to alert when `STALE` is present.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/redis/health" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/claims/health

_Merkl API_

> Check claim indexing sync across all chains

Always returns HTTP 200. `status` is `STALE` when claim indexing has fallen behind: either the latest on-chain claim has sat unprocessed for at least 2 hours (or no processing checkpoint exists yet), or an indexing source is at least 2 hours behind the live chain head. `OK` otherwise. Aggregated over all chains; chains whose status can't be computed (e.g. RPC unreachable) are skipped. Configure a keyword monitor to alert when `STALE` is present.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/claims/health" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/dynamic-data/health

_Merkl API_

> Check the update-dynamic-data job is running across chains

Always returns HTTP 200. `status` is `STALE` when the `update-dynamic-data` job (refreshes live opportunity/campaign APR, TVL and dailyRewards) has stopped completing its full run on any chain it runs on — a chain counts as degraded when its last completed run is over 45 minutes old. Chains that have never recorded a run (newly added / not yet scheduled) aren't counted. Configure a keyword monitor to alert when `STALE` is present.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/dynamic-data/health" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/historical/campaign/{campaignId}

_Merkl API_

> Campaign reward diff between two trees (BETA)

**Historical Campaign Diff**<p>Computes the difference in reward breakdowns for a given campaign between two merkle trees. Each tree is selected either by date (closest root on or before the date, via <code>startDate</code>/<code>endDate</code>) or by an explicit root hash (<code>startRoot</code>/<code>endRoot</code>). Returns per-recipient, per-reason breakdown diffs with non-zero changes only.</p><p><strong>Authentication:</strong> Requires a valid API key passed via the <code>Authorization</code> header.</p><p>⚠️ <strong>Beta:</strong> this endpoint is in beta. The behavior, response shape and data format may change at any time without notice. Historical data is only available from the configured cutoff date onwards.</p>

### Path parameters

- `campaignId` (string) _(required)_

### Query parameters

- `chainId` (string | number) _(required)_
- `startDate` (string)
- `endDate` (string)
- `startRoot` (string)
- `endRoot` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/historical/campaign/{campaignId}?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/historical/recipient/{recipient}

_Merkl API_

> Recipient reward diff between two trees (BETA)

**Historical Recipient Diff**<p>Computes the difference in reward breakdowns for a given recipient between two merkle trees. Each tree is selected either by date (closest root on or before the date, via <code>startDate</code>/<code>endDate</code>) or by an explicit root hash (<code>startRoot</code>/<code>endRoot</code>). Returns per-campaign, per-reason breakdown diffs with non-zero changes only.</p><p><strong>Authentication:</strong> Requires a valid API key passed via the <code>Authorization</code> header.</p><p>⚠️ <strong>Beta:</strong> this endpoint is in beta. The behavior, response shape and data format may change at any time without notice. Historical data is only available from the configured cutoff date onwards.</p>

### Path parameters

- `recipient` (string) _(required)_

### Query parameters

- `chainId` (string | number) _(required)_
- `startDate` (string)
- `endDate` (string)
- `startRoot` (string)
- `endRoot` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/historical/recipient/{recipient}?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/historical/tree

_Merkl API_

> Reward breakdowns of a single tree (BETA)

**Historical Tree Breakdowns**<p>Returns the cumulative reward breakdowns of a single merkle tree, selected either by <code>date</code> (closest root on or before the date) or by an explicit <code>root</code> hash. Results can be filtered by <code>campaignId</code> and/or <code>recipient</code>.</p><p><strong>Authentication:</strong> Requires a valid API key passed via the <code>Authorization</code> header.</p><p>⚠️ <strong>Beta:</strong> this endpoint is in beta. The behavior, response shape and data format may change at any time without notice. Historical data is only available from the configured cutoff date onwards.</p>

### Query parameters

- `chainId` (string | number) _(required)_
- `date` (string)
- `root` (string)
- `campaignId` (string)
- `recipient` (string)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/historical/tree?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/leaves/{recipient}/breakdowns

_Merkl API_

Returns paginated leaf breakdowns for a recipient, token, and chain, including both distributed and pending amounts. Supports filters on campaignId, opportunityId, and protocolId.

### Path parameters

- `recipient` (string) _(required)_

### Query parameters

- `tokenAddress` (string) _(required)_
- `distributionChainId` (string | number) _(required)_
- `campaignId` (string)
- `opportunityId` (string)
- `protocolId` (array)
- `page` (string | number)
- `items` (string | number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/leaves/{recipient}/breakdowns?tokenAddress=<tokenAddress>&distributionChainId=<distributionChainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/leaves/{recipient}/debt

_Merkl API_

Returns the outstanding overdistribution clawback debt for an address, per (chain, token): owed, recovered so far, and remaining. Empty array if the address has no configured debt.

### Path parameters

- `recipient` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/leaves/{recipient}/debt" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/roots/

_Merkl API_

Returns the last merkl roots recorded before the provided timestamps. Use chainId and timestamps query parameters to filter results.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `fromTimestamp` (string) _(required)_
- `toTimestamp` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/roots/?chainId=<chainId>&fromTimestamp=<fromTimestamp>&toTimestamp=<toTimestamp>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/roots/live

_Merkl API_

Returns all current live Merkl root hashes across all chains.

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/roots/live" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/node

_Merkl API_

> Check if an address was already labelled as specific by the Merkl Engine.

Check if a given address was already labelled as specific by the Merkl Engine. Use this endpoint to check for forwarders, pools, etc.

### Query parameters

- `chainId` (string | number)
- `addressOrId` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/node?addressOrId=<addressOrId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/node/protocols

_Merkl API_

Get the list of protocols that have indexed node sources available.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/node/protocols" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/node/protocol/{protocol}/chains

_Merkl API_

Get the chains configured for a specific protocol.

### Path parameters

- `protocol` (string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/node/protocol/{protocol}/chains" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/node/last-block

_Merkl API_

Get the most recent indexed block. If a protocol is provided, returns it for that protocol on the given chain; otherwise returns it for the chain across all protocols.

### Query parameters

- `chainId` (string | number) _(required)_
- `protocol` (string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string)

## Responses

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/node/last-block?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/node/oldest-block

_Merkl API_

Get the oldest indexed block. If a protocol is provided, returns it for that protocol on the given chain; otherwise returns it for the chain across all protocols.

### Query parameters

- `chainId` (string | number) _(required)_
- `protocol` (string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string)

## Responses

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/node/oldest-block?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/node/block-difference

_Merkl API_

Get the block difference (oldest to current). If a protocol is provided, returns it for that protocol on the given chain; otherwise returns it for the chain across all protocols.

### Query parameters

- `chainId` (string | number) _(required)_
- `protocol` (string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string | string)

## Responses

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/node/block-difference?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/offchain-billing/self/owed

_Merkl API_

Your creator's off-chain owed position (X-API-Key): credit balance, pending accrual, owed, and a per-campaign pending breakdown. Scoped to your own key.

## Responses

- **200** Off-chain owed position for a client

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/offchain-billing/self/owed" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/offchain-billing/self/pending

_Merkl API_

Just your creator's pending off-chain accrual (X-API-Key) — the USD not yet debited.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/offchain-billing/self/pending" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/offchain-billing/self/operations

_Merkl API_

Your creator's off-chain accrual debits (X-API-Key), newest first.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/offchain-billing/self/operations" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/{id}

_Merkl API_

Get a unique opportunity by ID (hash) or composite identifier (chainId-type-identifier). Use query parameters to include campaigns or filter results.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `test` (boolean)
- `point` (boolean)
- `tokenTypes` (array)
- `campaigns` (boolean)
- `excludeSubCampaigns` (boolean)

## Responses

- **200** Response for status 200
- **404** Response for status 404
- **500** Response for status 500

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/{id}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/{id}/storing-ids

_Merkl API_

Get the storingId(s) backing an opportunity, grouped by root campaign. Returns one tree per root campaign matching the requested statuses (default `LIVE`; past root campaigns are excluded). Each node lists its own storingIds, with sub-campaigns nested under `subCampaigns`. Sub-campaigns of a matching root are not status-filtered. The same storingId may appear in more than one tree. Stateless campaigns return an empty `storingIds` array.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `campaignStatus` (RegExp)

## Responses

- **200** Response for status 200
- **404** Response for status 404
- **500** Response for status 500

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/{id}/storing-ids" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/{id}/campaigns

_Merkl API_

Get a unique opportunity by ID (hash) or composite identifier (chainId-type-identifier), including related campaigns. Use query parameters to filter results.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `test` (boolean)
- `point` (boolean)
- `tokenTypes` (array)
- `campaigns` (boolean)
- `excludeSubCampaigns` (boolean)

## Responses

- **200** Response for status 200
- **404** Response for status 404
- **500** Response for status 500

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/{id}/campaigns" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/{id}/apr-records

_Merkl API_

Get historical APR records for an opportunity.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `from` (number)
- `to` (number)
- `grain` (string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/{id}/apr-records" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/{id}/tvl-records

_Merkl API_

Get historical TVL records for an opportunity.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `from` (number)
- `to` (number)
- `grain` (string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/{id}/tvl-records" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/{id}/native-apr-records

_Merkl API_

Get historical native APR records for an opportunity.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `from` (number)
- `to` (number)
- `grain` (string | string | string | string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/{id}/native-apr-records" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/

_Merkl API_

**Retrieve Multiple Opportunities**
<p>This endpoint enables you to search for opportunities by providing specific criteria through query parameters.</p>

#### Request Examples

##### List opportunities by protocol name
```bash
curl "https://api.merkl.xyz/v4/opportunities?name=Euler"
```

Returns all opportunities associated with the Euler protocol, including aggregate metrics.

##### Filter by tag
```bash
curl "https://api.merkl.xyz/v4/opportunities?tags=zksync"
```

Returns opportunities tagged with "zksync" across all supported protocols.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/count

_Merkl API_

Get the count of opportunities corresponding to the query.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/bins/apr

_Merkl API_

Get the APR distribution of opportunities matching the query, grouped into bins.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/bins/apr" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/bins/tvl

_Merkl API_

Get the TVL distribution of opportunities matching the query, grouped into bins.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/bins/tvl" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/bins/daily-rewards

_Merkl API_

Get the daily rewards distribution of opportunities matching the query, grouped into bins.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/bins/daily-rewards" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/aggregate/{field}

_Merkl API_

Aggregate opportunities by a specific field (chainId, protocolId, tags, etc.).

### Path parameters

- `field` (string | string | string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/aggregate/{field}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/aggregate/max/{field}

_Merkl API_

Get the maximum value for a specific field across filtered opportunities.

### Path parameters

- `field` (string | string | string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/aggregate/max/{field}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/opportunities/aggregate/min/{field}

_Merkl API_

Get the minimum value for a specific field across filtered opportunities.

### Path parameters

- `field` (string | string | string) _(required)_

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `search` (string)
- `campaignId` (string)
- `creatorSlug` (string)
- `chainId` (RegExp)
- `action` (string)
- `tokenTypes` (array)
- `point` (boolean)
- `type` (string)
- `creatorAddress` (string)
- `tags` (string)
- `test` (boolean)
- `minimumTvl` (number)
- `maximumTvl` (number)
- `minimumApr` (number)
- `maximumApr` (number)
- `minimumDailyRewards` (number)
- `maximumDailyRewards` (number)
- `minimumCreatedAt` (number)
- `maximumCreatedAt` (number)
- `status` (RegExp)
- `identifier` (string)
- `id` (string)
- `campaigns` (boolean)
- `tokens` (string)
- `stablecoin` (boolean)
- `rewardTokenSymbol` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `distributionTypes` (array)
- `mainProtocolId` (string)
- `programSlugs` (string)
- `chainName` (RegExp)
- `excludeSubCampaigns` (boolean)
- `explorerAddress` (string)
- `withInvalids` (boolean)
- `campaignTypes` (RegExp)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/opportunities/aggregate/min/{field}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/sofr-ratchet/campaign/{campaignId}

_Merkl API_

Current SOFR-spread-ratchet rate for a campaign, resolved from its own stored distribution settings (opportunityId, anchor, curve). Returns `campaignApr` (the baseline target or the boost gap, per the campaign's curve) plus the shared context: frozen mean TVL, last/next recalc, live SOFR, and the baseline/boosted APYs.

### Path parameters

- `campaignId` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/sofr-ratchet/campaign/{campaignId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/sofr-ratchet/opportunity/{id}

_Merkl API_

Current SOFR-spread-ratchet rate for an opportunity at an explicit anchor: frozen 14-day-mean TVL with last/next recalc, live SOFR, and the resulting baseline/boosted APYs. Computed on the fly from the same shared logic the engine distributes against.

### Path parameters

- `id` (string) _(required)_

### Query parameters

- `anchor` (number) _(required)_
- `at` (number)
- `period` (number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/sofr-ratchet/opportunity/{id}?anchor=<anchor>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/overrides/check

_Merkl API_

Validate if an override is allowed. Checks: (1) rewardToken cannot change, (2) amount cannot change, (3) startTimestamp cannot change after campaign starts, (4) endTimestamp must be in future.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "oldConfig": {},
    "newConfig": {}
  },
  "required": [
    "oldConfig",
    "newConfig"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "oldConfig": {},
    "newConfig": {}
  },
  "required": [
    "oldConfig",
    "newConfig"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "oldConfig": {},
    "newConfig": {}
  },
  "required": [
    "oldConfig",
    "newConfig"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/overrides/check" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/overrides/{id}/previous-configs

_Merkl API_

> Get previous campaign configs

Get all previous configs for a campaign, showing the opportunity each config was linked to before overrides

### Path parameters

- `id` (string) _(required)_

## Responses

- **200** Array of previous campaign configurations with their linked opportunities

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/overrides/{id}/previous-configs" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/campaigns/{id}/access/grant

_Merkl API_

Grant access to a private campaign for a specific address.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "userAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address to grant/revoke access",
      "type": "string"
    },
    "canManageAccess": {
      "description": "Whether the user can manage (grant/revoke) access for others",
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "userAddress"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "userAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address to grant/revoke access",
      "type": "string"
    },
    "canManageAccess": {
      "description": "Whether the user can manage (grant/revoke) access for others",
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "userAddress"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "userAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address to grant/revoke access",
      "type": "string"
    },
    "canManageAccess": {
      "description": "Whether the user can manage (grant/revoke) access for others",
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "userAddress"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/campaigns/{id}/access/grant" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# DELETE /v4/campaigns/{id}/access/revoke

_Merkl API_

Revoke access to a private campaign for a specific address.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "userAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address to grant/revoke access",
      "type": "string"
    },
    "canManageAccess": {
      "description": "Whether the user can manage (grant/revoke) access for others",
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "userAddress"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "userAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address to grant/revoke access",
      "type": "string"
    },
    "canManageAccess": {
      "description": "Whether the user can manage (grant/revoke) access for others",
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "userAddress"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "userAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address to grant/revoke access",
      "type": "string"
    },
    "canManageAccess": {
      "description": "Whether the user can manage (grant/revoke) access for others",
      "default": false,
      "type": "boolean"
    }
  },
  "required": [
    "userAddress"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/campaigns/{id}/access/revoke" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/campaigns/{id}/access/list

_Merkl API_

List all addresses currently granted access to a private campaign.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/campaigns/{id}/access/list" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/programs/

_Merkl API_

**Retrieve Multiple Programs**
<p>This endpoint enables you to search for programs by providing specific criteria through query parameters.</p>

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `slugs` (string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/programs/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/programs/{idOrSlug}

_Merkl API_

**Retrieve a Program by id or slug**
<p>This endpoint enables you to search for a program by providing its unique ID or slug identifier in the idOrSlug path parameter.</p>

### Path parameters

- `idOrSlug` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/programs/{idOrSlug}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/programs/count

_Merkl API_

Get the total count of all programs.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `name` (string)
- `slugs` (string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/programs/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/protocols/

_Merkl API_

List protocols supported and integrated by Merkl. Use query parameters to filter by chain ID, tags, or other criteria.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `id` (string)
- `test` (boolean)
- `ids` (array)
- `name` (string)
- `tags` (array)
- `opportunityTag` (string)
- `opportunityChain` (string | number)
- `status` (RegExp)
- `tokenTypes` (array)
- `excludeSubCampaigns` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/protocols/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/protocols/count

_Merkl API_

Get the number of protocols corresponding to the query. Use query parameters to filter the count.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `id` (string)
- `test` (boolean)
- `ids` (array)
- `name` (string)
- `tags` (array)
- `opportunityTag` (string)
- `opportunityChain` (string | number)
- `status` (RegExp)
- `tokenTypes` (array)
- `excludeSubCampaigns` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/protocols/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/protocols/{id}

_Merkl API_

Get a protocol by its ID or name using id path parameter. This endpoint searches by protocol ID first, then falls back to name.

### Path parameters

- `id` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/protocols/{id}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/reallocations/breakdown

_Merkl API_

**Retrieve Reallocation Breakdown**
<p>Returns aggregated reallocation amounts grouped by recipient and campaign.</p>
<p>Filters only successful reallocation operations (reason = "reallocation").</p>
<p>Use query parameters to filter by chain, recipients, and campaigns.</p>
<p><strong>Authentication:</strong> Requires a valid API key passed via the <code>Authorization</code> header.</p>

### Query parameters

- `chainId` (string | number) _(required)_
- `to` (array)
- `campaignIds` (array)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/reallocations/breakdown?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/referral/code

_Merkl API_

Returns the transaction to register user as a referrer on-chain and some additional state using chainId, referralKey, and address query parameters

### Query parameters

- `chainId` (number) _(required)_
- `referralKey` (string) _(required)_
- `address` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/referral/code?chainId=<chainId>&referralKey=<referralKey>&address=<address>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/referral/redeem

_Merkl API_

Returns the transaction to redeem a referral code on-chain and some additional state using chainId, referralKey, and code query parameters

### Query parameters

- `chainId` (number) _(required)_
- `referralKey` (string) _(required)_
- `code` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/referral/redeem?chainId=<chainId>&referralKey=<referralKey>&code=<code>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/

_Merkl API_

Returns all the addresses that received rewards for a given campaign, sorted by descending amounts. Use query parameters to filter by campaign ID, chain ID, and pagination.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `campaignId` (string) _(required)_
- `hide` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/?chainId=<chainId>&campaignId=<campaignId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/total

_Merkl API_

Returns the total amount distributed for a given campaign. Use query parameters to specify campaign ID and chain ID.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `campaignId` (string) _(required)_
- `hide` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/total?chainId=<chainId>&campaignId=<campaignId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/count

_Merkl API_

Returns the number of recipients that earned rewards in a given campaign. Use query parameters to specify campaign ID and chain ID.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `campaignId` (string) _(required)_
- `hide` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/count?chainId=<chainId>&campaignId=<campaignId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/rank

_Merkl API_

Returns the rank of a user in a campaign leaderboard, based on reward amount. Returns an empty array if the rank is not yet available.

### Query parameters

- `chainId` (string | number) _(required)_
- `campaignId` (string) _(required)_
- `userAddress` (string) _(required)_
- `hide` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/rank?chainId=<chainId>&campaignId=<campaignId>&userAddress=<userAddress>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/campaign/{campaignId}/list

_Merkl API_

Get rewards for a specific campaign by campaignId path parameter and list of addresses

### Path parameters

- `campaignId` (string) _(required)_

### Query parameters

- `addresses` (array) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/campaign/{campaignId}/list?addresses=<addresses>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/token/

_Merkl API_

Returns all the addresses that received rewards of a given token, sorted by descending amounts. Use query parameters to specify token address, chain ID, and pagination.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `address` (string) _(required)_
- `recipient` (string)
- `excludeAddresses` (string | array)
- `test` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/token/?chainId=<chainId>&address=<address>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/token/total

_Merkl API_

Returns the total amount distributed for a given token. Use query parameters to specify token address and chain ID.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `address` (string) _(required)_
- `recipient` (string)
- `excludeAddresses` (string | array)
- `test` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/token/total?chainId=<chainId>&address=<address>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/token/count

_Merkl API_

Returns the number of recipients that earned rewards in a given token. Use query parameters to specify token address and chain ID.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `address` (string) _(required)_
- `recipient` (string)
- `excludeAddresses` (string | array)
- `test` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/token/count?chainId=<chainId>&address=<address>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/token/unclaimed

_Merkl API_

Returns the total unclaimed amount (distributed minus claimed) for a given token. Use query parameters to specify token address and chain ID.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `chainId` (string | number) _(required)_
- `address` (string) _(required)_
- `recipient` (string)
- `excludeAddresses` (string | array)
- `test` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/token/unclaimed?chainId=<chainId>&address=<address>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/rewards/unclaim/

_Merkl API_

Returns the total of unclaimed rewards for given campaigns. Use query parameters to specify chain ID and campaign IDs.

### Query parameters

- `chainId` (string | number) _(required)_
- `campaignIds` (string | array) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/rewards/unclaim/?chainId=<chainId>&campaignIds=<campaignIds>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/rewards/unclaim/batch

_Merkl API_

Returns unclaimed rewards for campaigns across multiple chains in a single call. Pass an array of `{ campaignId, distributionChainId }` objects.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "campaigns": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "campaignId": {
            "description": "On-chain campaign ID (32-byte hex hash). See [ID types](/integrate-merkl/id-types).",
            "type": "string"
          },
          "distributionChainId": {
            "description": "Distribution chain ID (numeric, e.g. `1` for Ethereum). See [ID types](/integrate-merkl/id-types).",
            "anyOf": [
              {
                "format": "numeric",
                "default": 0,
                "type": "string"
              },
              {
                "description": "Distribution chain ID (numeric, e.g. `1` for Ethereum). See [ID types](/integrate-merkl/id-types).",
                "type": "number"
              }
            ]
          }
        },
        "required": [
          "campaignId",
          "distributionChainId"
        ]
      }
    }
  },
  "required": [
    "campaigns"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "campaigns": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "campaignId": {
            "description": "On-chain campaign ID (32-byte hex hash). See [ID types](/integrate-merkl/id-types).",
            "type": "string"
          },
          "distributionChainId": {
            "description": "Distribution chain ID (numeric, e.g. `1` for Ethereum). See [ID types](/integrate-merkl/id-types).",
            "anyOf": [
              {
                "format": "numeric",
                "default": 0,
                "type": "string"
              },
              {
                "description": "Distribution chain ID (numeric, e.g. `1` for Ethereum). See [ID types](/integrate-merkl/id-types).",
                "type": "number"
              }
            ]
          }
        },
        "required": [
          "campaignId",
          "distributionChainId"
        ]
      }
    }
  },
  "required": [
    "campaigns"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "campaigns": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "campaignId": {
            "description": "On-chain campaign ID (32-byte hex hash). See [ID types](/integrate-merkl/id-types).",
            "type": "string"
          },
          "distributionChainId": {
            "description": "Distribution chain ID (numeric, e.g. `1` for Ethereum). See [ID types](/integrate-merkl/id-types).",
            "anyOf": [
              {
                "format": "numeric",
                "default": 0,
                "type": "string"
              },
              {
                "description": "Distribution chain ID (numeric, e.g. `1` for Ethereum). See [ID types](/integrate-merkl/id-types).",
                "type": "number"
              }
            ]
          }
        },
        "required": [
          "campaignId",
          "distributionChainId"
        ]
      }
    }
  },
  "required": [
    "campaigns"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/rewards/unclaim/batch" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/schemas/

_Merkl API_

> List schema groups (BETA)

**List schema groups**<p>Returns every schema group exposed by this API. A <em>group</em> binds an enum (e.g. <code>CampaignType</code>) to a family of TypeBox JSON Schemas describing the inputs the Merkl engine accepts for each value of that enum.</p><p>Current groups:</p><ul><li><code>campaignType</code> — config inputs of a campaign of a given <code>CampaignType</code>.</li><li><code>campaignTypeExtended</code> — same as <code>campaignType</code> plus <code>distributionChainId</code> and <code>campaignId</code>.</li><li><code>distributionMethod</code> — parameters of a given <code>DistributionMethod</code>.</li><li><code>computeScoreMethod</code> — parameters of a given <code>ComputeScoreMethod</code>.</li><li><code>hookType</code> — parameters of a given <code>HookType</code>.</li><li><code>processorType</code> — config of a given <code>ProcessorType</code>.</li></ul><p>Pair this endpoint with <a href="#tag/Enums"><code>/v4/enums</code></a> for the enum value ↔ key mapping.</p><p>⚠️ <strong>Beta:</strong> response shape may change without notice.</p>

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/schemas/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/schemas/{groupName}

_Merkl API_

> List schemas in a group (BETA)

**List schemas in a group**<p>Returns every entry of the enum backing the given group. Each entry contains the addressable <code>value</code>, the enum <code>key</code> and an optional human-readable <code>description</code>. Use one of these <code>value</code>s (or the <code>key</code>) as <code>:typeId</code> in <code>GET /v4/schemas/:groupName/:typeId</code>.</p><p>Example: <code>GET /v4/schemas/distributionMethod</code> returns the list of <code>DistributionMethod</code> values for which a JSON Schema is available.</p><p>Responds <code>404</code> if <code>groupName</code> is not a known group — see <code>GET /v4/schemas</code> for the list of valid groups.</p>

### Path parameters

- `groupName` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/schemas/{groupName}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/schemas/{groupName}/{typeId}

_Merkl API_

> Get raw JSON Schema for a typed input (BETA)

**Get raw JSON Schema for a typed input**<p>Returns the raw TypeBox JSON Schema describing the inputs accepted for a specific entry of a group. The returned object is a standard JSON Schema document and can be consumed directly by tooling such as <code>ajv</code>, <code>openapi-typescript</code>, <code>json-schema-to-ts</code> or <code>quicktype</code>.</p><p><code>:typeId</code> accepts either:</p><ul><li>the enum <strong>value</strong> — e.g. <code>1</code> for <code>CampaignType.INVALID</code>, or <code>FIX_APR</code> for <code>DistributionMethod.FIX_APR</code>;</li><li>the enum <strong>key</strong> — e.g. <code>INVALID</code> for <code>CampaignType.INVALID</code>.</li></ul><p>Examples:</p><ul><li><code>GET /v4/schemas/campaignType/1</code></li><li><code>GET /v4/schemas/distributionMethod/FIX_APR</code></li><li><code>GET /v4/schemas/hookType/APIBOOST</code></li></ul><p>Responds <code>404</code> if either <code>groupName</code> is unknown or <code>typeId</code> does not match any value/key of the underlying enum.</p><p>⚠️ <strong>Beta:</strong> the returned schema may evolve as the engine evolves.</p>

### Path parameters

- `groupName` (string) _(required)_
- `typeId` (string) _(required)_

## Responses

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/schemas/{groupName}/{typeId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/templates/

_Merkl API_

Get all templates filtered by query parameters

### Query parameters

- `protocolId` (string)
- `search` (string)
- `action` (array)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/templates/" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/templates/count

_Merkl API_

Count templates matching the query filters

### Query parameters

- `protocolId` (string)
- `search` (string)
- `action` (array)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/templates/count" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/templates/{id}

_Merkl API_

Find one template by ID (UUID) or name

### Path parameters

- `id` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/templates/{id}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/tokens/prices/history

_Merkl API_

Get historical price snapshots for a token. Resolve by symbol (optionally scoped to a chainId) or by exact chainId+address.

### Query parameters

- `symbol` (string)
- `address` (string)
- `chainId` (string | number)
- `from` (string | integer)
- `to` (string | integer)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/tokens/prices/history" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/tokens/reward

_Merkl API_

Get all tokens that are accepted as reward tokens across all chains.

### Query parameters

- `chainId` (RegExp)
- `search` (string)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/tokens/reward" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/tokens/reward/{chainId}

_Merkl API_

Get the list of tokens that are accepted as reward tokens on a given chain.

### Path parameters

- `chainId` (string | number) _(required)_

### Query parameters

- `tokenTypes` (array)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/tokens/reward/{chainId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/tokens/whitelist

_Merkl API_

Submit a token whitelist request for review.

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "explainer": {
      "maxLength": 500,
      "description": "Short explanation of the token to add.",
      "type": "string"
    },
    "address": {
      "maxLength": 66,
      "description": "Token address in checksum format.",
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the network where the token is deployed.",
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "description": "Chain ID of the network where the token is deployed.",
          "type": "number"
        }
      ]
    },
    "iconUrl": {
      "maxLength": 1024,
      "description": "Publicly accessible HTTPS URL for the token icon. Mutually exclusive with iconFile.",
      "type": "string"
    },
    "iconFile": {
      "type": "object",
      "properties": {
        "data": {
          "maxLength": 1398102,
          "description": "Base64-encoded icon file bytes (max 1 MB raw).",
          "type": "string"
        },
        "mimeType": {
          "description": "Image MIME type (e.g. image/png).",
          "type": "string"
        },
        "filename": {
          "maxLength": 255,
          "description": "Original filename (e.g. token.svg).",
          "type": "string"
        }
      },
      "required": [
        "data",
        "mimeType",
        "filename"
      ]
    },
    "protocolName": {
      "maxLength": 100,
      "description": "Name of the protocol submitting the request.",
      "type": "string"
    },
    "requesterType": {
      "description": "Whether the requester submits as an individual or a company. Required.",
      "anyOf": [
        {
          "const": "individual",
          "type": "string"
        },
        {
          "const": "company",
          "type": "string"
        }
      ]
    },
    "companyName": {
      "maxLength": 100,
      "description": "Company name — required when requesterType is 'company'.",
      "type": "string"
    },
    "telegramHandle": {
      "maxLength": 100,
      "description": "Telegram handle to notify once the token is whitelisted.",
      "type": "string"
    },
    "displaySymbol": {
      "maxLength": 50,
      "description": "Override symbol shown in the UI. Defaults to on-chain symbol.",
      "type": "string"
    },
    "coingeckoApiId": {
      "maxLength": 100,
      "description": "CoinGecko API ID for price sourcing and APR/TVL calculation.",
      "type": "string"
    },
    "tokenName": {
      "maxLength": 100,
      "description": "Token name, resolved client-side.",
      "type": "string"
    },
    "tokenSymbol": {
      "maxLength": 50,
      "description": "Token symbol, resolved client-side.",
      "type": "string"
    }
  },
  "required": [
    "explainer",
    "address",
    "chainId",
    "protocolName",
    "requesterType",
    "telegramHandle"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "explainer": {
      "maxLength": 500,
      "description": "Short explanation of the token to add.",
      "type": "string"
    },
    "address": {
      "maxLength": 66,
      "description": "Token address in checksum format.",
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the network where the token is deployed.",
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "description": "Chain ID of the network where the token is deployed.",
          "type": "number"
        }
      ]
    },
    "iconUrl": {
      "maxLength": 1024,
      "description": "Publicly accessible HTTPS URL for the token icon. Mutually exclusive with iconFile.",
      "type": "string"
    },
    "iconFile": {
      "type": "object",
      "properties": {
        "data": {
          "maxLength": 1398102,
          "description": "Base64-encoded icon file bytes (max 1 MB raw).",
          "type": "string"
        },
        "mimeType": {
          "description": "Image MIME type (e.g. image/png).",
          "type": "string"
        },
        "filename": {
          "maxLength": 255,
          "description": "Original filename (e.g. token.svg).",
          "type": "string"
        }
      },
      "required": [
        "data",
        "mimeType",
        "filename"
      ]
    },
    "protocolName": {
      "maxLength": 100,
      "description": "Name of the protocol submitting the request.",
      "type": "string"
    },
    "requesterType": {
      "description": "Whether the requester submits as an individual or a company. Required.",
      "anyOf": [
        {
          "const": "individual",
          "type": "string"
        },
        {
          "const": "company",
          "type": "string"
        }
      ]
    },
    "companyName": {
      "maxLength": 100,
      "description": "Company name — required when requesterType is 'company'.",
      "type": "string"
    },
    "telegramHandle": {
      "maxLength": 100,
      "description": "Telegram handle to notify once the token is whitelisted.",
      "type": "string"
    },
    "displaySymbol": {
      "maxLength": 50,
      "description": "Override symbol shown in the UI. Defaults to on-chain symbol.",
      "type": "string"
    },
    "coingeckoApiId": {
      "maxLength": 100,
      "description": "CoinGecko API ID for price sourcing and APR/TVL calculation.",
      "type": "string"
    },
    "tokenName": {
      "maxLength": 100,
      "description": "Token name, resolved client-side.",
      "type": "string"
    },
    "tokenSymbol": {
      "maxLength": 50,
      "description": "Token symbol, resolved client-side.",
      "type": "string"
    }
  },
  "required": [
    "explainer",
    "address",
    "chainId",
    "protocolName",
    "requesterType",
    "telegramHandle"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "explainer": {
      "maxLength": 500,
      "description": "Short explanation of the token to add.",
      "type": "string"
    },
    "address": {
      "maxLength": 66,
      "description": "Token address in checksum format.",
      "type": "string"
    },
    "chainId": {
      "description": "Chain ID of the network where the token is deployed.",
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "description": "Chain ID of the network where the token is deployed.",
          "type": "number"
        }
      ]
    },
    "iconUrl": {
      "maxLength": 1024,
      "description": "Publicly accessible HTTPS URL for the token icon. Mutually exclusive with iconFile.",
      "type": "string"
    },
    "iconFile": {
      "type": "object",
      "properties": {
        "data": {
          "maxLength": 1398102,
          "description": "Base64-encoded icon file bytes (max 1 MB raw).",
          "type": "string"
        },
        "mimeType": {
          "description": "Image MIME type (e.g. image/png).",
          "type": "string"
        },
        "filename": {
          "maxLength": 255,
          "description": "Original filename (e.g. token.svg).",
          "type": "string"
        }
      },
      "required": [
        "data",
        "mimeType",
        "filename"
      ]
    },
    "protocolName": {
      "maxLength": 100,
      "description": "Name of the protocol submitting the request.",
      "type": "string"
    },
    "requesterType": {
      "description": "Whether the requester submits as an individual or a company. Required.",
      "anyOf": [
        {
          "const": "individual",
          "type": "string"
        },
        {
          "const": "company",
          "type": "string"
        }
      ]
    },
    "companyName": {
      "maxLength": 100,
      "description": "Company name — required when requesterType is 'company'.",
      "type": "string"
    },
    "telegramHandle": {
      "maxLength": 100,
      "description": "Telegram handle to notify once the token is whitelisted.",
      "type": "string"
    },
    "displaySymbol": {
      "maxLength": 50,
      "description": "Override symbol shown in the UI. Defaults to on-chain symbol.",
      "type": "string"
    },
    "coingeckoApiId": {
      "maxLength": 100,
      "description": "CoinGecko API ID for price sourcing and APR/TVL calculation.",
      "type": "string"
    },
    "tokenName": {
      "maxLength": 100,
      "description": "Token name, resolved client-side.",
      "type": "string"
    },
    "tokenSymbol": {
      "maxLength": 50,
      "description": "Token symbol, resolved client-side.",
      "type": "string"
    }
  },
  "required": [
    "explainer",
    "address",
    "chainId",
    "protocolName",
    "requesterType",
    "telegramHandle"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/tokens/whitelist" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/users/{address}/rewards

_Merkl API_

Get the rewards associated to a user on a given chain.

#### Request Examples

##### Fetch rewards for a user wallet on a specific chain
```bash
curl "https://api.merkl.xyz/v4/users/0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb/rewards?chainId=1"
```

Use the returned proofs to build a claim transaction [integrating-user-reward](https://docs.merkl.xyz/integrate-merkl/app#integrating-user-reward)

Retrieve user rewards aggregated by chain. Use query parameters to filter by chain IDs, reward type, and claimability.

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainId` (array) _(required)_
- `reloadChainId` (string | number)
- `test` (boolean)
- `claimableOnly` (boolean)
- `breakdownPage` (string | number)
- `type` (string | string | string)
- `showPrivate` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/rewards?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/protocols/{protocolId}/rewards

_Merkl API_

Retrieve claimable rewards for a user scoped to a single protocol. Breakdowns and amounts reflect only campaigns attributed to the requested protocol. The returned `proofs` and `root` still claim the full per-token leaf on-chain.

### Path parameters

- `address` (string) _(required)_
- `protocolId` (string) _(required)_

### Query parameters

- `chainId` (array) _(required)_
- `reloadChainId` (string | number)
- `test` (boolean)
- `claimableOnly` (boolean)
- `breakdownPage` (string | number)
- `type` (string | string | string)
- `showPrivate` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/protocols/{protocolId}/rewards?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/terms

_Merkl API_

Check if a user address has signed Merkl's terms for a specific chain. Provide the user's wallet address and chain ID.

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainId` (string | number) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/terms?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/recipient/{token}

_Merkl API_

Get the recipient address for a given user address and specific token.

### Path parameters

- `address` (string) _(required)_
- `token` (string) _(required)_

### Query parameters

- `chainId` (string | number) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/recipient/{token}?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/operator/{operatorAddress}

_Merkl API_

Check if an address is an operator for a given user address.

### Path parameters

- `address` (string) _(required)_
- `operatorAddress` (string) _(required)_

### Query parameters

- `chainId` (string | number) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/operator/{operatorAddress}?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/wrapped

_Merkl API_

Get a summary of a user's claimed rewards, including their most-used protocol and most-claimed token by USD value.

### Path parameters

- `address` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/wrapped" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/rewards/stats

_Merkl API_

Lightweight USD totals for a user — total earned, currently claimable, and pending. Supports optional filters: chainId, chains, tokens, protocols, isTest, isPreTGE.

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainId` (array)
- `tokens` (array)
- `protocols` (array)
- `tags` (array)
- `isTest` (boolean)
- `isPreTGE` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/rewards/stats" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/rewards/summary

_Merkl API_

Per-chain rewards rollup with USD totals and per-token raw amounts. A lightweight alternative to /rewards that omits full campaign breakdowns. Supports optional filters: chainId, chains, tokens, protocols, isTest, isPreTGE.

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainId` (array)
- `tokens` (array)
- `protocols` (array)
- `tags` (array)
- `isTest` (boolean)
- `isPreTGE` (boolean)
- `reloadChainId` (string | number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/rewards/summary" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/rewards/active-opportunities

_Merkl API_

Active opportunities for a user — LIVE status with rewards still claimable or pending. Aggregated by opportunity and sorted by APR descending. Settled amounts reflect recent distribution state and may be up to 30 minutes behind; pending amounts are computed live. `withStoringIds=true` additionally returns the storingIds backing each opportunity, for mapping the caller's on-chain positions (analytics positions route).

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `chainId` (array)
- `tokens` (array)
- `protocols` (array)
- `tags` (array)
- `isTest` (boolean)
- `isPreTGE` (boolean)
- `withStoringIds` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/rewards/active-opportunities" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/rewards/chains/{chainId}/breakdowns

_Merkl API_

Per-chain opportunity breakdown for a user. Aggregated by opportunity with one row per token carrying claimed, pending, and server-computed claimable amounts.

### Path parameters

- `address` (string) _(required)_
- `chainId` (string | number) _(required)_

### Query parameters

- `tokens` (array)
- `protocols` (array)
- `tags` (array)
- `isTest` (boolean)
- `isPreTGE` (boolean)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/rewards/chains/{chainId}/breakdowns" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/users/{address}/rewards/breakdowns

_Merkl API_

Per-chain rewards with full opportunity breakdowns and proofs. Returns the same shape as `/v4/users/{address}/rewards` but with the breakdowns included. Limited to roughly 1000 breakdowns per response; responses exceeding this limit omit the breakdowns. For high-volume users, paginate via `/v4/leaves/{recipient}/breakdowns` instead.

### Path parameters

- `address` (string) _(required)_

### Query parameters

- `tags` (string)
- `chainIds` (array)
- `reloadChainId` (string | number)
- `test` (boolean)
- `claimableOnly` (boolean)
- `showPrivate` (boolean)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/users/{address}/rewards/breakdowns" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/volume/entries

_Merkl API_

List volume entries, filterable by program, clientId, chainId and a timestamp range (all optional, AND-combined). Paginated via page/items. Each entry includes its parent VolumeConfig.

### Query parameters

- `page` (string | number)
- `items` (string | number)
- `program` (string)
- `clientId` (string)
- `chainId` (string | number)
- `fromTimestamp` (string | number)
- `toTimestamp` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/volume/entries" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/volume/user

_Merkl API_

Aggregated volume for a single user (recipient), filterable by program, clientId, chainId and a timestamp range (all optional, AND-combined). Returns the summed amountUSD and matching entry count.

### Query parameters

- `recipient` (string) _(required)_
- `program` (string)
- `clientId` (string)
- `chainId` (string | number)
- `fromTimestamp` (string | number)
- `toTimestamp` (string | number)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/volume/user?recipient=<recipient>" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/volume/boost

_Merkl API_

Compute a boost per address: the summed VolumeEntry amount over the config matching clientId and program. Each posted address is returned with its boost ("0" when none match); the zero address is always included with "0".

### Query parameters

- `clientId` (string) _(required)_
- `program` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "addresses": {
      "maxItems": 500,
      "description": "Wallet addresses to look up (case-insensitive). Up to 500 per request.",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "addresses"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "addresses": {
      "maxItems": 500,
      "description": "Wallet addresses to look up (case-insensitive). Up to 500 per request.",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "addresses"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "addresses": {
      "maxItems": 500,
      "description": "Wallet addresses to look up (case-insensitive). Up to 500 per request.",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "addresses"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/volume/boost?clientId=<clientId>&program=<program>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/volume/facets

_Merkl API_

List the available programs and client ids to filter volume entries by.

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/volume/facets" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /graphql/v1

_Merkl API_

GraphQL endpoint. POST a query to execute it, or open the URL in a browser to load GraphiQL for interactive exploration of the schema.

## Example request

```bash
curl -X GET "https://api.merkl.xyz//graphql/v1" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /graphql/v1

_Merkl API_

GraphQL endpoint. POST a query to execute it, or open the URL in a browser to load GraphiQL for interactive exploration of the schema.

## Example request

```bash
curl -X POST "https://api.merkl.xyz//graphql/v1" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PUT /graphql/v1

_Merkl API_

GraphQL endpoint. POST a query to execute it, or open the URL in a browser to load GraphiQL for interactive exploration of the schema.

## Example request

```bash
curl -X PUT "https://api.merkl.xyz//graphql/v1" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# DELETE /graphql/v1

_Merkl API_

GraphQL endpoint. POST a query to execute it, or open the URL in a browser to load GraphiQL for interactive exploration of the schema.

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//graphql/v1" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PATCH /graphql/v1

_Merkl API_

GraphQL endpoint. POST a query to execute it, or open the URL in a browser to load GraphiQL for interactive exploration of the schema.

## Example request

```bash
curl -X PATCH "https://api.merkl.xyz//graphql/v1" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/internal/diffs/

_Merkl API_

Returns paginated parent Diff rows, count, and summary for a given chain

### Query parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_
- `tokenAddress` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

### Header parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_
- `tokenAddress` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/?chainId=<chainId>&root=<root>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "root: <root>" \
  -H "tokenAddress: <tokenAddress>" \
  -H "recipient: <recipient>" \
  -H "sort: <sort>" \
  -H "order: <order>" \
  -H "page: <page>" \
  -H "items: <items>"
```

---

# GET /v4/internal/diffs/leaves

_Merkl API_

Returns paginated parent Leaf rows, count, and summary for a given chain

### Query parameters

- `chainId` (string | number) _(required)_
- `tokenAddress` (string) _(required)_
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

### Header parameters

- `chainId` (string | number) _(required)_
- `tokenAddress` (string) _(required)_
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/leaves?chainId=<chainId>&tokenAddress=<tokenAddress>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "tokenAddress: <tokenAddress>" \
  -H "recipient: <recipient>" \
  -H "sort: <sort>" \
  -H "order: <order>" \
  -H "page: <page>" \
  -H "items: <items>"
```

---

# GET /v4/internal/diffs/breakdowns

_Merkl API_

Returns paginated DiffBreakdown rows, count, and summary for a given chain and root

### Query parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_
- `tokenAddress` (string)
- `campaignId` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

### Header parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_
- `tokenAddress` (string)
- `campaignId` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/breakdowns?chainId=<chainId>&root=<root>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "root: <root>" \
  -H "tokenAddress: <tokenAddress>" \
  -H "campaignId: <campaignId>" \
  -H "recipient: <recipient>" \
  -H "sort: <sort>" \
  -H "order: <order>" \
  -H "page: <page>" \
  -H "items: <items>"
```

---

# GET /v4/internal/diffs/breakdowns/count

_Merkl API_

Returns count of DiffBreakdown rows matching filters

### Query parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_
- `tokenAddress` (string)
- `campaignId` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

### Header parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_
- `tokenAddress` (string)
- `campaignId` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/breakdowns/count?chainId=<chainId>&root=<root>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "root: <root>" \
  -H "tokenAddress: <tokenAddress>" \
  -H "campaignId: <campaignId>" \
  -H "recipient: <recipient>" \
  -H "sort: <sort>" \
  -H "order: <order>" \
  -H "page: <page>" \
  -H "items: <items>"
```

---

# GET /v4/internal/diffs/tokens

_Merkl API_

Returns distinct tokens present in DiffBreakdown rows for a given chain and root

### Query parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_

### Header parameters

- `chainId` (string | number) _(required)_
- `root` (string) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/tokens?chainId=<chainId>&root=<root>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "root: <root>"
```

---

# GET /v4/internal/diffs/roots

_Merkl API_

Returns recent MerklRoots for a chain (last 7 days)

### Query parameters

- `chainId` (string | number) _(required)_

### Header parameters

- `chainId` (string | number) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/roots?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>"
```

---

# GET /v4/internal/diffs/leaf-breakdowns

_Merkl API_

Returns paginated LeafBreakdown rows, count, and summary for a given chain and token

### Query parameters

- `chainId` (string | number) _(required)_
- `tokenAddress` (string) _(required)_
- `campaignId` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

### Header parameters

- `chainId` (string | number) _(required)_
- `tokenAddress` (string) _(required)_
- `campaignId` (string)
- `recipient` (string)
- `sort` (RegExp)
- `order` (RegExp)
- `page` (string | number)
- `items` (string | number)

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/leaf-breakdowns?chainId=<chainId>&tokenAddress=<tokenAddress>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "tokenAddress: <tokenAddress>" \
  -H "campaignId: <campaignId>" \
  -H "recipient: <recipient>" \
  -H "sort: <sort>" \
  -H "order: <order>" \
  -H "page: <page>" \
  -H "items: <items>"
```

---

# GET /v4/internal/diffs/leaf-tokens

_Merkl API_

Returns distinct tokens present in LeafBreakdown rows for a chain

### Query parameters

- `chainId` (string | number) _(required)_

### Header parameters

- `chainId` (string | number) _(required)_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/diffs/leaf-tokens?chainId=<chainId>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>"
```

---

# POST /v4/internal/key-value-stores

_Merkl API_

Create a new key-value store config (BackOffice only)

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "key": {
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Unique human-readable key (alphanumeric, hyphens, underscores)",
      "type": "string"
    },
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "accessMode": {
      "anyOf": [
        {
          "const": "PUBLIC",
          "type": "string"
        },
        {
          "const": "API_KEY",
          "type": "string"
        }
      ]
    },
    "type": {
      "description": "Semantic type — determines the required JSON shape of entry values",
      "anyOf": [
        {
          "const": "WHITELIST",
          "type": "string"
        },
        {
          "const": "BLACKLIST",
          "type": "string"
        },
        {
          "const": "BOOST",
          "type": "string"
        },
        {
          "const": "REFERRER",
          "type": "string"
        },
        {
          "const": "FORWARDER",
          "type": "string"
        },
        {
          "const": "APR",
          "type": "string"
        }
      ]
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "default": 100000,
      "type": "number"
    },
    "publicRead": {
      "default": true,
      "type": "boolean"
    },
    "ownerAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address of the config owner (must have an API key for API_KEY mode)",
      "type": "string"
    }
  },
  "required": [
    "key",
    "accessMode",
    "type",
    "ownerAddress"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "key": {
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Unique human-readable key (alphanumeric, hyphens, underscores)",
      "type": "string"
    },
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "accessMode": {
      "anyOf": [
        {
          "const": "PUBLIC",
          "type": "string"
        },
        {
          "const": "API_KEY",
          "type": "string"
        }
      ]
    },
    "type": {
      "description": "Semantic type — determines the required JSON shape of entry values",
      "anyOf": [
        {
          "const": "WHITELIST",
          "type": "string"
        },
        {
          "const": "BLACKLIST",
          "type": "string"
        },
        {
          "const": "BOOST",
          "type": "string"
        },
        {
          "const": "REFERRER",
          "type": "string"
        },
        {
          "const": "FORWARDER",
          "type": "string"
        },
        {
          "const": "APR",
          "type": "string"
        }
      ]
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "default": 100000,
      "type": "number"
    },
    "publicRead": {
      "default": true,
      "type": "boolean"
    },
    "ownerAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address of the config owner (must have an API key for API_KEY mode)",
      "type": "string"
    }
  },
  "required": [
    "key",
    "accessMode",
    "type",
    "ownerAddress"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "key": {
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^[a-zA-Z0-9_-]+$",
      "description": "Unique human-readable key (alphanumeric, hyphens, underscores)",
      "type": "string"
    },
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "accessMode": {
      "anyOf": [
        {
          "const": "PUBLIC",
          "type": "string"
        },
        {
          "const": "API_KEY",
          "type": "string"
        }
      ]
    },
    "type": {
      "description": "Semantic type — determines the required JSON shape of entry values",
      "anyOf": [
        {
          "const": "WHITELIST",
          "type": "string"
        },
        {
          "const": "BLACKLIST",
          "type": "string"
        },
        {
          "const": "BOOST",
          "type": "string"
        },
        {
          "const": "REFERRER",
          "type": "string"
        },
        {
          "const": "FORWARDER",
          "type": "string"
        },
        {
          "const": "APR",
          "type": "string"
        }
      ]
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "default": 100000,
      "type": "number"
    },
    "publicRead": {
      "default": true,
      "type": "boolean"
    },
    "ownerAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Ethereum address of the config owner (must have an API key for API_KEY mode)",
      "type": "string"
    }
  },
  "required": [
    "key",
    "accessMode",
    "type",
    "ownerAddress"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/internal/key-value-stores" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/internal/key-value-stores

_Merkl API_

List all key-value store configs (BackOffice only)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/key-value-stores" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PATCH /v4/internal/key-value-stores/{key}

_Merkl API_

Update a config (BackOffice only)

### Path parameters

- `key` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "publicRead": {
      "type": "boolean"
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    }
  }
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "publicRead": {
      "type": "boolean"
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    }
  }
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "description": {
      "maxLength": 512,
      "type": "string"
    },
    "publicRead": {
      "type": "boolean"
    },
    "sizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    }
  }
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X PATCH "https://api.merkl.xyz//v4/internal/key-value-stores/{key}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# DELETE /v4/internal/key-value-stores/{key}

_Merkl API_

Delete a config and all entries (BackOffice only)

### Path parameters

- `key` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/internal/key-value-stores/{key}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/internal/key-value-stores/quotas

_Merkl API_

Grant a self-serve creator quota (BackOffice only)

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "ownerAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Grantee address",
      "type": "string"
    },
    "maxConfigs": {
      "minimum": 1,
      "description": "Max configs this user may own",
      "type": "number"
    },
    "maxSizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "description": "Ceiling on per-config sizeLimit",
      "type": "number"
    },
    "allowedTypes": {
      "minItems": 1,
      "description": "Config types this user may create",
      "type": "array",
      "items": {
        "description": "Semantic type — determines the required JSON shape of entry values",
        "anyOf": [
          {
            "const": "WHITELIST",
            "type": "string"
          },
          {
            "const": "BLACKLIST",
            "type": "string"
          },
          {
            "const": "BOOST",
            "type": "string"
          },
          {
            "const": "REFERRER",
            "type": "string"
          },
          {
            "const": "FORWARDER",
            "type": "string"
          },
          {
            "const": "APR",
            "type": "string"
          }
        ]
      }
    }
  },
  "required": [
    "ownerAddress",
    "maxConfigs",
    "maxSizeLimit",
    "allowedTypes"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "ownerAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Grantee address",
      "type": "string"
    },
    "maxConfigs": {
      "minimum": 1,
      "description": "Max configs this user may own",
      "type": "number"
    },
    "maxSizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "description": "Ceiling on per-config sizeLimit",
      "type": "number"
    },
    "allowedTypes": {
      "minItems": 1,
      "description": "Config types this user may create",
      "type": "array",
      "items": {
        "description": "Semantic type — determines the required JSON shape of entry values",
        "anyOf": [
          {
            "const": "WHITELIST",
            "type": "string"
          },
          {
            "const": "BLACKLIST",
            "type": "string"
          },
          {
            "const": "BOOST",
            "type": "string"
          },
          {
            "const": "REFERRER",
            "type": "string"
          },
          {
            "const": "FORWARDER",
            "type": "string"
          },
          {
            "const": "APR",
            "type": "string"
          }
        ]
      }
    }
  },
  "required": [
    "ownerAddress",
    "maxConfigs",
    "maxSizeLimit",
    "allowedTypes"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "ownerAddress": {
      "pattern": "^0x[a-fA-F0-9]{40}$",
      "description": "Grantee address",
      "type": "string"
    },
    "maxConfigs": {
      "minimum": 1,
      "description": "Max configs this user may own",
      "type": "number"
    },
    "maxSizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "description": "Ceiling on per-config sizeLimit",
      "type": "number"
    },
    "allowedTypes": {
      "minItems": 1,
      "description": "Config types this user may create",
      "type": "array",
      "items": {
        "description": "Semantic type — determines the required JSON shape of entry values",
        "anyOf": [
          {
            "const": "WHITELIST",
            "type": "string"
          },
          {
            "const": "BLACKLIST",
            "type": "string"
          },
          {
            "const": "BOOST",
            "type": "string"
          },
          {
            "const": "REFERRER",
            "type": "string"
          },
          {
            "const": "FORWARDER",
            "type": "string"
          },
          {
            "const": "APR",
            "type": "string"
          }
        ]
      }
    }
  },
  "required": [
    "ownerAddress",
    "maxConfigs",
    "maxSizeLimit",
    "allowedTypes"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/internal/key-value-stores/quotas" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/internal/key-value-stores/quotas

_Merkl API_

List all self-serve creator quotas (BackOffice only)

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/key-value-stores/quotas" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PATCH /v4/internal/key-value-stores/quotas/{address}

_Merkl API_

Update a creator quota (BackOffice only)

### Path parameters

- `address` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "maxConfigs": {
      "minimum": 1,
      "type": "number"
    },
    "maxSizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    },
    "allowedTypes": {
      "minItems": 1,
      "type": "array",
      "items": {
        "description": "Semantic type — determines the required JSON shape of entry values",
        "anyOf": [
          {
            "const": "WHITELIST",
            "type": "string"
          },
          {
            "const": "BLACKLIST",
            "type": "string"
          },
          {
            "const": "BOOST",
            "type": "string"
          },
          {
            "const": "REFERRER",
            "type": "string"
          },
          {
            "const": "FORWARDER",
            "type": "string"
          },
          {
            "const": "APR",
            "type": "string"
          }
        ]
      }
    }
  }
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "maxConfigs": {
      "minimum": 1,
      "type": "number"
    },
    "maxSizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    },
    "allowedTypes": {
      "minItems": 1,
      "type": "array",
      "items": {
        "description": "Semantic type — determines the required JSON shape of entry values",
        "anyOf": [
          {
            "const": "WHITELIST",
            "type": "string"
          },
          {
            "const": "BLACKLIST",
            "type": "string"
          },
          {
            "const": "BOOST",
            "type": "string"
          },
          {
            "const": "REFERRER",
            "type": "string"
          },
          {
            "const": "FORWARDER",
            "type": "string"
          },
          {
            "const": "APR",
            "type": "string"
          }
        ]
      }
    }
  }
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "maxConfigs": {
      "minimum": 1,
      "type": "number"
    },
    "maxSizeLimit": {
      "minimum": 1,
      "maximum": 1000000,
      "type": "number"
    },
    "allowedTypes": {
      "minItems": 1,
      "type": "array",
      "items": {
        "description": "Semantic type — determines the required JSON shape of entry values",
        "anyOf": [
          {
            "const": "WHITELIST",
            "type": "string"
          },
          {
            "const": "BLACKLIST",
            "type": "string"
          },
          {
            "const": "BOOST",
            "type": "string"
          },
          {
            "const": "REFERRER",
            "type": "string"
          },
          {
            "const": "FORWARDER",
            "type": "string"
          },
          {
            "const": "APR",
            "type": "string"
          }
        ]
      }
    }
  }
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X PATCH "https://api.merkl.xyz//v4/internal/key-value-stores/quotas/{address}" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# DELETE /v4/internal/key-value-stores/quotas/{address}

_Merkl API_

Revoke a creator quota (BackOffice only)

### Path parameters

- `address` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X DELETE "https://api.merkl.xyz//v4/internal/key-value-stores/quotas/{address}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# POST /v4/internal/payload/gnosis

_Merkl API_

Analyse the campaigns created by a future transaction. For large Safe files (>50 campaigns), consider splitting into multiple requests.

## Request body

**`application/json`**
```json
{
  "additionalProperties": true,
  "type": "object",
  "properties": {
    "chainId": {
      "description": "Chain ID where the campaign is deployed",
      "type": "string"
    },
    "transactions": {
      "additionalProperties": true,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contractInputsValues": {
            "nullable": true,
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object",
                "properties": {
                  "newCampaign": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  },
  "required": [
    "chainId",
    "transactions"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "additionalProperties": true,
  "type": "object",
  "properties": {
    "chainId": {
      "description": "Chain ID where the campaign is deployed",
      "type": "string"
    },
    "transactions": {
      "additionalProperties": true,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contractInputsValues": {
            "nullable": true,
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object",
                "properties": {
                  "newCampaign": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  },
  "required": [
    "chainId",
    "transactions"
  ]
}
```
**`multipart/form-data`**
```json
{
  "additionalProperties": true,
  "type": "object",
  "properties": {
    "chainId": {
      "description": "Chain ID where the campaign is deployed",
      "type": "string"
    },
    "transactions": {
      "additionalProperties": true,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contractInputsValues": {
            "nullable": true,
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object",
                "properties": {
                  "newCampaign": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  },
  "required": [
    "chainId",
    "transactions"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/internal/payload/gnosis" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/internal/payload/gnosis/async

_Merkl API_

Start async analysis of campaigns from a Safe file. Returns a job ID immediately. Use GET /payload/jobs/:jobId to check status and retrieve results.

## Request body

**`application/json`**
```json
{
  "additionalProperties": true,
  "type": "object",
  "properties": {
    "chainId": {
      "description": "Chain ID where the campaign is deployed",
      "type": "string"
    },
    "transactions": {
      "additionalProperties": true,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contractInputsValues": {
            "nullable": true,
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object",
                "properties": {
                  "newCampaign": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  },
  "required": [
    "chainId",
    "transactions"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "additionalProperties": true,
  "type": "object",
  "properties": {
    "chainId": {
      "description": "Chain ID where the campaign is deployed",
      "type": "string"
    },
    "transactions": {
      "additionalProperties": true,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contractInputsValues": {
            "nullable": true,
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object",
                "properties": {
                  "newCampaign": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  },
  "required": [
    "chainId",
    "transactions"
  ]
}
```
**`multipart/form-data`**
```json
{
  "additionalProperties": true,
  "type": "object",
  "properties": {
    "chainId": {
      "description": "Chain ID where the campaign is deployed",
      "type": "string"
    },
    "transactions": {
      "additionalProperties": true,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "contractInputsValues": {
            "nullable": true,
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object",
                "properties": {
                  "newCampaign": {
                    "type": "string"
                  }
                }
              },
              {
                "type": "null"
              }
            ]
          }
        }
      }
    }
  },
  "required": [
    "chainId",
    "transactions"
  ]
}
```

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/internal/payload/gnosis/async" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/internal/payload/jobs/{jobId}

_Merkl API_

Get the status of an async Safe file analysis job. Poll this endpoint to check progress and retrieve results when completed.

### Path parameters

- `jobId` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/payload/jobs/{jobId}" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# GET /v4/internal/transactions/find-creation-hash

_Merkl API_

> Find Creation Transaction Hash

This endpoint searches for the transaction hash that created a campaign by chain ID and campaign ID. Uses binary search with archive node calls to efficiently locate the creation block, then searches for NewCampaign events. Returns the transaction hash, block number, and explorer URL if found, or null values if not found.

### Query parameters

- `chainId` (string | number) _(required)_
- `campaignId` (string) _(required)_

### Header parameters

- `chainId` (string | number) _(required)_
- `campaignId` (string) _(required)_

## Responses

- **200** Response for status 200

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/transactions/find-creation-hash?chainId=<chainId>&campaignId=<campaignId>" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "chainId: <chainId>" \
  -H "campaignId: <campaignId>"
```

---

# POST /v4/internal/users/

_Merkl API_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "description": "User wallet address",
      "type": "string"
    },
    "tags": {
      "description": "Tags associated with the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "address",
    "tags"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "description": "User wallet address",
      "type": "string"
    },
    "tags": {
      "description": "Tags associated with the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "address",
    "tags"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "address": {
      "description": "User wallet address",
      "type": "string"
    },
    "tags": {
      "description": "Tags associated with the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "address",
    "tags"
  ]
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/internal/users/" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# GET /v4/internal/users/tags

_Merkl API_

## Example request

```bash
curl -X GET "https://api.merkl.xyz//v4/internal/users/tags" \
  -H "x-api-key: YOUR_API_KEY"
```

---

# PATCH /v4/internal/users/{address}/tags

_Merkl API_

### Path parameters

- `address` (string) _(required)_

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "add": {
      "description": "Tags to add to the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "remove": {
      "description": "Tags to remove from the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "add",
    "remove"
  ]
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "add": {
      "description": "Tags to add to the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "remove": {
      "description": "Tags to remove from the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "add",
    "remove"
  ]
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "add": {
      "description": "Tags to add to the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "remove": {
      "description": "Tags to remove from the user",
      "type": "array",
      "items": {
        "type": "string"
      }
    }
  },
  "required": [
    "add",
    "remove"
  ]
}
```

## Example request

```bash
curl -X PATCH "https://api.merkl.xyz//v4/internal/users/{address}/tags" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```

---

# POST /v4/engine/tokens/synthetic

_Merkl API_

Upsert a synthetic token with engine-provided metadata (no on-chain fetch)

## Request body

**`application/json`**
```json
{
  "type": "object",
  "properties": {
    "chainId": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "address": {
      "type": "string"
    },
    "symbol": {
      "type": "string"
    },
    "decimals": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "price": {
      "type": "number"
    }
  },
  "required": [
    "chainId",
    "address",
    "symbol",
    "decimals"
  ],
  "additionalProperties": false
}
```
**`application/x-www-form-urlencoded`**
```json
{
  "type": "object",
  "properties": {
    "chainId": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "address": {
      "type": "string"
    },
    "symbol": {
      "type": "string"
    },
    "decimals": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "price": {
      "type": "number"
    }
  },
  "required": [
    "chainId",
    "address",
    "symbol",
    "decimals"
  ],
  "additionalProperties": false
}
```
**`multipart/form-data`**
```json
{
  "type": "object",
  "properties": {
    "chainId": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "address": {
      "type": "string"
    },
    "symbol": {
      "type": "string"
    },
    "decimals": {
      "anyOf": [
        {
          "format": "numeric",
          "default": 0,
          "type": "string"
        },
        {
          "type": "number"
        }
      ]
    },
    "price": {
      "type": "number"
    }
  },
  "required": [
    "chainId",
    "address",
    "symbol",
    "decimals"
  ],
  "additionalProperties": false
}
```

## Example request

```bash
curl -X POST "https://api.merkl.xyz//v4/engine/tokens/synthetic" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ ... }'
```