{
  "openapi": "3.0.0",
  "paths": {
    "/v1/risk/address": {
      "get": {
        "description": "Returns the risk score associated with the specified address.",
        "operationId": "getRiskPath",
        "parameters": [
          {
            "name": "address",
            "required": false,
            "in": "query",
            "description": "Address to search",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "network",
            "required": false,
            "in": "query",
            "description": "Network ID of the address. Supports multiple networks including eth, solana, stellar, osmosis-1, dydx-mainnet-1, cosmoshub-4, neutron-1, and others. If omitted, will attempt to automatically infer from address format (eth, stellar, solana).",
            "schema": {
              "example": "solana",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Transactions associated with a specific address. This includes both incoming and outgoing transactions.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RiskScore"
                }
              }
            }
          }
        },
        "summary": "Get Address Risk Score",
        "tags": [
          "Risk"
        ]
      }
    },
    "/v1/risk/transaction": {
      "get": {
        "description": "Returns the risk score associated with the specified transaction.",
        "operationId": "getTransactionRiskScore",
        "parameters": [
          {
            "name": "transaction",
            "required": false,
            "in": "query",
            "description": "Transaction Hash",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "network",
            "required": false,
            "in": "query",
            "description": "Network ID of the transaction. Supports multiple networks including ethereum, solana, osmosis-1, dydx-mainnet-1, cosmoshub-4, neutron-1, stellar, and others. Defaults to solana if omitted.",
            "schema": {
              "example": "solana",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "summary": "Get Transaction Risk Score",
        "tags": [
          "Risk"
        ]
      }
    },
    "/v1/risk/history": {
      "get": {
        "description": "Returns risk assessment history (newest first).",
        "operationId": "getTokenRiskAssessmentHistory",
        "parameters": [
          {
            "name": "workspace",
            "required": true,
            "in": "query",
            "description": "Workspace identifier",
            "schema": {
              "example": "tl95vahzp0002zfu04n1zevvp",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": ""
          }
        },
        "summary": "Get Token Risk Assessment History",
        "tags": [
          "Risk"
        ]
      }
    },
    "/v1/risk/token": {
      "get": {
        "description": "Returns comprehensive risk assessment for a Solana token using ML analysis.",
        "operationId": "getTokenRiskAssessment",
        "parameters": [
          {
            "name": "asset_address",
            "required": true,
            "in": "query",
            "description": "Asset identifier (chain-agnostic). Currently only Solana token mint (base58, 32–44 chars) is supported.",
            "schema": {
              "example": "So11111111111111111111111111111111111111112",
              "type": "string"
            }
          },
          {
            "name": "network",
            "required": true,
            "in": "query",
            "description": "Blockchain network for token risk (only solana supported)",
            "schema": {
              "example": "solana",
              "type": "string",
              "enum": [
                "solana"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Token risk assessment with detailed factors and scoring",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenRiskResponse"
                }
              }
            }
          }
        },
        "summary": "Get Token Risk Assessment",
        "tags": [
          "Risk"
        ]
      }
    },
    "/v1/risk/payment": {
      "get": {
        "description": "Analyzes cross-chain payments to assess risk using advanced heuristic rules and ML-powered analysis. Evaluates sender and recipient addresses based on transaction history, behavioral patterns, interaction history, address poisoning detection, malicious connections, and security indicators.",
        "operationId": "getPaymentRiskAssessment",
        "parameters": [
          {
            "name": "sender_address",
            "required": true,
            "in": "query",
            "description": "Sender blockchain address",
            "schema": {
              "example": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
              "type": "string"
            }
          },
          {
            "name": "recipient_address",
            "required": true,
            "in": "query",
            "description": "Recipient blockchain address",
            "schema": {
              "example": "7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi",
              "type": "string"
            }
          },
          {
            "name": "amount",
            "required": true,
            "in": "query",
            "description": "Payment amount in USD equivalent (must be positive)",
            "schema": {
              "minimum": 0.01,
              "example": 1000,
              "type": "number"
            }
          },
          {
            "name": "sender_network",
            "required": true,
            "in": "query",
            "description": "Sender blockchain network (e.g., solana, osmosis, ethereum)",
            "schema": {
              "example": "solana",
              "type": "string"
            }
          },
          {
            "name": "recipient_network",
            "required": true,
            "in": "query",
            "description": "Recipient blockchain network",
            "schema": {
              "example": "solana",
              "type": "string"
            }
          },
          {
            "name": "sender_token",
            "required": false,
            "in": "query",
            "description": "Token/denom being sent (optional, enables token risk assessment)",
            "schema": {
              "example": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
              "type": "string"
            }
          },
          {
            "name": "recipient_token",
            "required": false,
            "in": "query",
            "description": "Token/denom being received (optional)",
            "schema": {
              "example": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
              "type": "string"
            }
          },
          {
            "name": "timestamp",
            "required": false,
            "in": "query",
            "description": "Payment timestamp in ISO 8601 format (optional)",
            "schema": {
              "example": "2025-01-15T10:30:00Z",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Payment risk assessment with individual risk factors and overall risk level",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentRiskResponse"
                }
              }
            }
          }
        },
        "summary": "Get Payment Risk Assessment",
        "tags": [
          "Risk"
        ]
      }
    },
    "/v1/risk/sanctions/{address}": {
      "get": {
        "description": "Check if an address is blacklisted by token issuers (Tether, Circle, Coinbase, Paxos) or OFAC sanctioned. Supports Ethereum, Tron, and Solana networks.",
        "operationId": "getBlacklistCheck",
        "parameters": [
          {
            "name": "address",
            "required": true,
            "in": "path",
            "description": "Blockchain address to check (EVM, Solana, or Tron format)",
            "schema": {
              "example": "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a",
              "type": "string"
            }
          },
          {
            "name": "network",
            "required": false,
            "in": "query",
            "description": "Filter by blockchain network. If omitted, checks all networks.",
            "schema": {
              "enum": [
                "ethereum",
                "tron",
                "solana"
              ],
              "type": "string"
            }
          },
          {
            "name": "include_details",
            "required": false,
            "in": "query",
            "description": "Include detailed event history and attribution (default: true)",
            "schema": {
              "default": true,
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Blacklist and sanctions check result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BlacklistCheckResponse"
                }
              }
            }
          }
        },
        "summary": "Check Blacklist & OFAC Sanctions",
        "tags": [
          "Risk"
        ]
      }
    },
    "/v1/simulate/solana/transactions": {
      "post": {
        "description": "Simulate multiple Solana transactions to get the address balance changes after the transactions are executed.",
        "operationId": "simulateSolanaTxs",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "transactions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "payload": {
                          "type": "string"
                        },
                        "encoding_type": {
                          "type": "string",
                          "enum": [
                            "base64",
                            "base58"
                          ]
                        }
                      },
                      "required": [
                        "payload",
                        "encoding_type"
                      ]
                    }
                  }
                },
                "required": [
                  "transactions"
                ]
              },
              "examples": {
                "request": {
                  "value": {
                    "transactions": [
                      {
                        "payload": "ASBmxvNLxR9UJImZ0AW5jg8dnPRJ4WrgTfVPzYJTw/dsdxJLQ2R3PL6sOGZRpm8Cvj3CCj487knAlkVDjrurJQ+AAQAHDwi27GhTZy4xU+no9CPSYfbdV1f7fPh2AZ8ugRR0lzY/NkTF/pcxbJ1GWhb/ojq1kpL45RJn2LGQqvS+DlQNKMJDuMya7qyNXnGZUaTmp2cnsKVtfo4Ls7tredY1eFVh/pL42Zv7ym+AgvHJQrwx2Uy3BthbLxxvtbLp7x4PC0b0lKed/Fk9s8DKxlNmWP+yQe4ZLmsyhIKUU9zZSCjcvGiv0erWb2FXM10++aHVXhcOjcwm3j+hU8QjFjPAG893CbFODeVen7qGOW6/1UjP+MkgEerHt1uqmy2caob1oXFB9fvkBoqq3bIiQD6qx3uSmgTZ1H+10FAQReZ/sk63f2sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAABHnVW/IxwG7udMVuzmgVB/2xst6j9I5RArHNola8E48FSlNamSkhBk0k6HFg2jh8fDW13bySu4HkH6hAQQVEjYyXJY9OJInxuz0QKRSODYMLWhOZ2v8QhASOe9jb6fhZtD/6J/XX9kp0wJsfKVh53ksJqzbfyd1RSzIap7OM5ejl4fbczcd5b+eKD48WExJdmg2tkPhcrXKsnw6Eytv9rt7t5tBFxI1Qc4SYWt2OkQNrwLSbBkWaZ+daWcdmirykCQkABQKwcQsACAIABgwCAAAAYwgAAAAAAAAMBgAHACQIJgEBDAYAAwAqCCYBAQwGAAUALggmAQEMBgAHACQIJgEBDAYAAgAtCCYBAQpCJgAHBQouCg0KJwAPBwIQEQ4lJismJgsAIiotAyECHx4gBCMrJgAdAxkFGxwaGCwoAAAVKRMSFxYUBQcoKCYIKAEKNeUXy5d6460qBAAAAFYA+mQAAS8AAGQBAhEBZAIDJwFkAwAAtVsSAAAAAOvQWxIAAAAAAAAACwARci1mOjM1ODY0MTczOTpyYTIElfeMHpclyjALvoOYBNZHC6S6vuMHe9I5nP8MmmxUl0cDiISKBAyGAom8+jUvkKtv40MXcOaoCkpAbJnSTRzNhDSJRQydxNnFgwYLDhANCAoCDA+OaHTLsrJF6N6xUSsg3E+nAZQJes71crtX3lTKNrmUFQaYlJecnZYFkxWZi5vSaTvsE8UgBxGyDP8AGoLYuuKa0FyIvnJZ6Xhha+SUoAaIwIeFwYYA",
                        "encoding_type": "base64"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "summary": "Simulate Solana transactions",
        "tags": [
          "Simulator"
        ]
      }
    },
    "/v1/simulate/solana/transaction": {
      "post": {
        "description": "Simulate a Solana transaction to get the address balance changes after the transaction is executed.",
        "operationId": "simulateSolanaTx",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulateSolanaTxDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        },
        "summary": "Simulate Solana Transaction",
        "tags": [
          "Simulator"
        ]
      }
    },
    "/v1/simulate/{network}/transaction": {
      "post": {
        "description": "Simulate a Cosmos SDK based blockchain transaction to get the address balance changes after the transaction is executed.",
        "operationId": "simulateTx",
        "parameters": [
          {
            "name": "network",
            "required": true,
            "in": "path",
            "description": "The network to simulate the transaction on",
            "schema": {
              "enum": [
                "osmosis-1",
                "neutron-1"
              ],
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulateTxDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Simulated transaction result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulatedTx"
                }
              }
            }
          }
        },
        "summary": "Simulate Cosmos Transaction",
        "tags": [
          "Simulator"
        ]
      }
    },
    "/v2/risk/address": {
      "get": {
        "description": "Returns a risk assessment for the specified address, including an overall risk severity and the attribution, exposure, and behaviour signals that contributed to it. Evidence is not included; fetch it via `/v2/risk/evidence/:screenId`.",
        "operationId": "getAddressRisk",
        "parameters": [
          {
            "name": "address",
            "required": true,
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "window",
            "required": false,
            "in": "query",
            "description": "Time window for analysis: 30d, 90d, 180d, 365d, or all.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_evidence",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RiskAssessmentDto"
                }
              }
            }
          }
        },
        "summary": "Get Address Risk Assessment",
        "tags": [
          "Risk v2"
        ]
      }
    },
    "/v2/risk/address/batch": {
      "get": {
        "description": "Returns risk assessments for up to 50 addresses. Network is derived per-address. Evidence is fetched separately via `/v2/risk/evidence/:screenId`.",
        "operationId": "getAddressRiskBatch",
        "parameters": [
          {
            "name": "addresses",
            "required": true,
            "in": "query",
            "description": "Comma-separated list of addresses (max 50).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "window",
            "required": false,
            "in": "query",
            "description": "Time window for analysis: 30d, 90d, 180d, 365d, or all.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "include_evidence",
            "required": false,
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchRiskAssessmentDto"
                }
              }
            }
          }
        },
        "summary": "Score Multiple Addresses",
        "tags": [
          "Risk v2"
        ]
      }
    },
    "/v2/risk/history": {
      "get": {
        "description": "Returns the most recent screening assessments for the workspace inferred from the API key. Use `limit` (1-100, default 10) for page size and `offset` to paginate. Returns empty when the key has no associated workspace.",
        "operationId": "getHistory",
        "parameters": [
          {
            "name": "offset",
            "required": false,
            "in": "query",
            "description": "Number of records to skip. Defaults to 0.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Page size, 1-100 inclusive. Defaults to 10.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HistoryResponseDto"
                }
              }
            }
          }
        },
        "summary": "List Screening History",
        "tags": [
          "Risk v2"
        ]
      }
    },
    "/v2/risk/evidence/{screenId}": {
      "get": {
        "description": "Returns the full evidence breakdown for a previously issued screen_id, grouped by pillar (attribution, exposure, behaviour) and signal, alongside the original risk assessment. Scoped to the calling workspace.",
        "operationId": "getEvidence",
        "parameters": [
          {
            "name": "screenId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvidenceResponseDto"
                }
              }
            }
          }
        },
        "summary": "Get Evidence by screen_id",
        "tags": [
          "Risk v2"
        ]
      }
    },
    "/v2/risk/config": {
      "get": {
        "description": "Returns the active risk configuration for your workspace. A workspace with no stored config returns empty arrays for all three pillars — nothing from the signals catalogue is auto-applied.",
        "operationId": "getConfig",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RiskConfigSpecDto"
                }
              }
            }
          }
        },
        "summary": "Get Workspace Risk Configuration",
        "tags": [
          "Risk v2"
        ]
      },
      "patch": {
        "description": "Partial update — include only the fields you want to change. Rows are matched by `signal`/`behaviour` id; omitted fields on a matched row are preserved; rows not mentioned are untouched. Unknown signal or behaviour IDs are rejected with 400.",
        "operationId": "patchConfig",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchRiskConfigDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RiskConfigSpecDto"
                }
              }
            }
          }
        },
        "summary": "Patch Workspace Risk Configuration",
        "tags": [
          "Risk v2"
        ]
      }
    },
    "/v2/risk/signals": {
      "get": {
        "description": "Returns the catalogue of available attribution signals, exposure signals, and behaviours. This is read-only metadata — not auto-applied to workspace configs.",
        "operationId": "getSignals",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SignalsCatalogueDto"
                }
              }
            }
          }
        },
        "summary": "List Available Signals and Behaviours",
        "tags": [
          "Risk v2"
        ]
      }
    },
    "/v1/risk/channels": {
      "get": {
        "description": "Returns every non-deleted alert channel for your workspace, including disabled ones. Each item carries `enabled` (your on/off state) and `connected` (delivery readiness). To hide a channel, delete it — disabling only stops delivery.",
        "operationId": "listChannels",
        "parameters": [],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAlertChannelsResponseDto"
                }
              }
            }
          }
        },
        "summary": "List alert channels for the caller workspace",
        "tags": [
          "Channels"
        ]
      },
      "post": {
        "description": "Creates a single channel for your workspace. Slack, Discord, and generic webhooks require params.webhook_url; PagerDuty requires params.routing_key; Email requires params.recipients (array of addresses); incident.io requires params.url; Telegram params are generated server-side.",
        "operationId": "createChannel",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAlertChannelDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertChannelDto"
                }
              }
            }
          }
        },
        "summary": "Create a channel",
        "tags": [
          "Channels"
        ]
      },
      "put": {
        "description": "Batch create, update, or soft-delete alert channels for your workspace. Each operation specifies an action (\"add\", \"update\", or \"remove\") and the channel data.",
        "operationId": "updateChannels",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateChannelsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateChannelsResponseDto"
                }
              }
            }
          }
        },
        "summary": "Add, update, or remove alert channels",
        "tags": [
          "Channels"
        ]
      }
    },
    "/v1/risk/channels/{channel_id}": {
      "get": {
        "description": "Returns the details of one alert channel that belongs to your workspace. Disabled channels are still returned (200); only deleted channels return 404.",
        "operationId": "getChannel",
        "parameters": [
          {
            "name": "channel_id",
            "required": true,
            "in": "path",
            "description": "The alert channel id.",
            "schema": {
              "example": "44444444-4444-4444-4444-444444444445",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertChannelDto"
                }
              }
            }
          }
        },
        "summary": "Fetch a single alert channel",
        "tags": [
          "Channels"
        ]
      },
      "delete": {
        "description": "Soft-deletes one channel owned by your workspace: it is disabled and hidden from list/get, but the row is retained (only `deleted_at` is stamped).",
        "operationId": "deleteChannel",
        "parameters": [
          {
            "name": "channel_id",
            "required": true,
            "in": "path",
            "description": "The channel id.",
            "schema": {
              "example": "44444444-4444-4444-4444-444444444445",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteAlertChannelResponseDto"
                }
              }
            }
          }
        },
        "summary": "Delete a channel",
        "tags": [
          "Channels"
        ]
      }
    },
    "/v1/risk/alert-templates": {
      "get": {
        "description": "Browse the alert rule templates your workspace has access to. Narrow the results by network, severity, or tags, or type a few words to search by name or description.",
        "operationId": "listTemplates",
        "parameters": [
          {
            "name": "network",
            "required": false,
            "in": "query",
            "description": "Comma-separated list of network slugs to filter by (e.g. `eth,sol`). Selects rule types that have a template on any of these networks; the returned group still lists all networks the rule supports.",
            "schema": {
              "example": "eth,sol",
              "type": "string"
            }
          },
          {
            "name": "search_string",
            "required": false,
            "in": "query",
            "description": "Case-insensitive search string matched against `label` and `description`.",
            "schema": {
              "example": "large transfer",
              "type": "string"
            }
          },
          {
            "name": "tag",
            "required": false,
            "in": "query",
            "description": "Comma-separated list of tags to filter by (e.g. `defi,transfer`).",
            "schema": {
              "example": "defi,transfer",
              "type": "string"
            }
          },
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "description": "Comma-separated list of severity levels to filter by (e.g. `low,medium,high`).",
            "schema": {
              "example": "high",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAlertTemplatesResponseDto"
                }
              }
            }
          }
        },
        "summary": "List alert rule templates available to the workspace",
        "tags": [
          "Alert Templates"
        ]
      }
    },
    "/v1/risk/alert-templates/{template_id}": {
      "get": {
        "description": "Returns everything about one alert rule template — its message, severity, tags, and the fields you need to fill in when turning it into an active alert rule.",
        "operationId": "getTemplate",
        "parameters": [
          {
            "name": "template_id",
            "required": true,
            "in": "path",
            "description": "The ID of the alert rule template you want to retrieve.",
            "schema": {
              "example": "1",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertTemplateDto"
                }
              }
            }
          }
        },
        "summary": "Get a single alert rule template",
        "tags": [
          "Alert Templates"
        ]
      }
    },
    "/v1/risk/alert-events": {
      "get": {
        "description": "Returns a cursor-paginated list of the workspace alert events, newest first. Filter by network, severity, resolution status, transaction hash, date range, or full-text search. Use `meta.next_cursor` / `meta.previous_cursor` to navigate pages.",
        "operationId": "listEvents",
        "parameters": [
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Maximum number of records to return (1-100). Defaults to 10.",
            "schema": {
              "minimum": 1,
              "maximum": 100,
              "default": 10,
              "example": 20,
              "type": "number"
            }
          },
          {
            "name": "cursor",
            "required": false,
            "in": "query",
            "description": "Opaque pagination cursor. Omit for the first page, then pass `meta.next_cursor` / `meta.previous_cursor` from a previous response to move between pages. `meta.first_page_cursor` (`A`) and `meta.last_page_cursor` (`Z`) jump to the first/last page. Results are ordered newest-first by a server-side cursor; treat the value as opaque — do not construct or modify it.",
            "schema": {
              "example": "eyJwIjoyLCJjIjoiMjkxNzM0NDYyNDg0NDM0OTk1MyIsImIiOmZhbHNlfQ",
              "type": "string"
            }
          },
          {
            "name": "network",
            "required": false,
            "in": "query",
            "description": "Filter by network slug (e.g. `ethereum`, `solana`).",
            "schema": {
              "example": "ethereum",
              "type": "string"
            }
          },
          {
            "name": "tx_hash",
            "required": false,
            "in": "query",
            "description": "Filter by exact transaction hash.",
            "schema": {
              "example": "0xabc123...def456",
              "type": "string"
            }
          },
          {
            "name": "alert_rule_id",
            "required": false,
            "in": "query",
            "description": "Filter by the alert rule that triggered the event.",
            "schema": {
              "example": "123456789012345678",
              "type": "string"
            }
          },
          {
            "name": "start_date",
            "required": false,
            "in": "query",
            "description": "Start of date range in `YYYY-MM-DD` format (inclusive, UTC).",
            "schema": {
              "example": "2026-05-01",
              "type": "string"
            }
          },
          {
            "name": "end_date",
            "required": false,
            "in": "query",
            "description": "End of date range in `YYYY-MM-DD` format (inclusive, UTC).",
            "schema": {
              "example": "2026-05-31",
              "type": "string"
            }
          },
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "description": "Comma-separated list of severity levels to filter by (e.g. `low,medium,high`).",
            "schema": {
              "example": "high,medium",
              "type": "string"
            }
          },
          {
            "name": "search_string",
            "required": false,
            "in": "query",
            "description": "Case-insensitive search across event caption and addresses involved.",
            "schema": {
              "example": "0x742d35",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAlertEventsResponseDto"
                }
              }
            }
          }
        },
        "summary": "List alert events for the workspace",
        "tags": [
          "Alert Events"
        ]
      }
    },
    "/v1/risk/alert-events/{event_id}": {
      "get": {
        "description": "Fetches a single alert event by its CUID. The response includes an `access_type` field that indicates the caller's access relationship to the event.",
        "operationId": "getEvent",
        "parameters": [
          {
            "name": "event_id",
            "required": true,
            "in": "path",
            "description": "CUID of the alert event to retrieve.",
            "schema": {
              "example": "clxyz1234abcd",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertEventDto"
                }
              }
            }
          }
        },
        "summary": "Get a single alert event by ID",
        "tags": [
          "Alert Events"
        ]
      }
    },
    "/v1/risk/alert-rules": {
      "get": {
        "description": "Returns every active alert rule that belongs to your workspace. Filter by network, severity, or a name search.",
        "operationId": "listRules",
        "parameters": [
          {
            "name": "network",
            "required": false,
            "in": "query",
            "description": "Comma-separated list of network slugs to filter by (e.g. `eth,sol`).",
            "schema": {
              "example": "eth,sol",
              "type": "string"
            }
          },
          {
            "name": "severity",
            "required": false,
            "in": "query",
            "description": "Comma-separated list of severity levels to filter by (e.g. `low,medium,high`).",
            "schema": {
              "example": "high",
              "type": "string"
            }
          },
          {
            "name": "search_string",
            "required": false,
            "in": "query",
            "description": "Case-insensitive search string matched against rule `name`.",
            "schema": {
              "example": "high gas",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAlertRulesResponseDto"
                }
              }
            }
          }
        },
        "summary": "List alert rules for the caller workspace",
        "tags": [
          "Alert Rules"
        ]
      },
      "post": {
        "description": "Creates an alert rule from a registered template. Supply the template id; rule_type, network, and runner_id are copied from it (not supplied).",
        "operationId": "createRule",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAlertRuleDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleDto"
                }
              }
            }
          }
        },
        "summary": "Create an alert rule",
        "tags": [
          "Alert Rules"
        ]
      }
    },
    "/v1/risk/alert-rules/{rule_id}": {
      "get": {
        "description": "Returns one alert rule that belongs to your workspace.",
        "operationId": "getRule",
        "parameters": [
          {
            "name": "rule_id",
            "required": true,
            "in": "path",
            "description": "The alert rule id.",
            "schema": {
              "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleDto"
                }
              }
            }
          }
        },
        "summary": "Fetch a single alert rule",
        "tags": [
          "Alert Rules"
        ]
      },
      "patch": {
        "description": "Partially updates a rule. Only the supplied fields change. Changing `parameters` bumps the rule's `version` and archives the previous version. To change channels, use PUT /:rule_id/channels.",
        "operationId": "patchRule",
        "parameters": [
          {
            "name": "rule_id",
            "required": true,
            "in": "path",
            "description": "The alert rule id.",
            "schema": {
              "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchAlertRuleDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleDto"
                }
              }
            }
          }
        },
        "summary": "Update an alert rule",
        "tags": [
          "Alert Rules"
        ]
      },
      "delete": {
        "description": "Soft-deletes the rule: it is disabled and hidden from list/get, but the row is retained in the database (only `deleted_at` is stamped).",
        "operationId": "deleteRule",
        "parameters": [
          {
            "name": "rule_id",
            "required": true,
            "in": "path",
            "description": "The alert rule id.",
            "schema": {
              "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteAlertRuleResponseDto"
                }
              }
            }
          }
        },
        "summary": "Delete an alert rule",
        "tags": [
          "Alert Rules"
        ]
      }
    },
    "/v1/risk/alert-rules/{rule_id}/channels": {
      "put": {
        "description": "Replaces the rule's subscribed channels with the supplied set. Each entry is { alert_channel_id, min_severity? }; alert_channel_id must be a channel in your workspace. Omit min_severity (or null) for no severity floor. Pass an empty array to clear.",
        "operationId": "linkChannels",
        "parameters": [
          {
            "name": "rule_id",
            "required": true,
            "in": "path",
            "description": "The alert rule id.",
            "schema": {
              "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkRuleChannelsDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AlertRuleDto"
                }
              }
            }
          }
        },
        "summary": "Link channels to an alert rule",
        "tags": [
          "Alert Rules"
        ]
      }
    }
  },
  "info": {
    "title": "Range Risk API",
    "description": "The Range Risk API for risk assessment of crypto addresses.",
    "version": "1.7.11",
    "contact": {}
  },
  "tags": [
    {
      "name": "Risk",
      "description": "Get risk information about a crypto address."
    },
    {
      "name": "Risk v2",
      "description": "Address risk assessment, workspace configuration, and signals catalogue (API v2)."
    },
    {
      "name": "Simulator",
      "description": "Simulate a transaction on a network."
    },
    {
      "name": "Alert Templates",
      "description": "Browse alert rule templates available to the workspace."
    },
    {
      "name": "Alert Rules",
      "description": "Create and manage workspace alert rules."
    },
    {
      "name": "Alert Events",
      "description": "List and retrieve fired alert events."
    },
    {
      "name": "Channels",
      "description": "Configure alert delivery channels."
    }
  ],
  "servers": [
    {
      "url": "https://api.range.org",
      "description": "Range API Server"
    }
  ],
  "components": {
    "securitySchemes": {
      "Authorization": {
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "Use Authorization: Bearer <api-key>",
        "type": "http"
      }
    },
    "schemas": {
      "CursorMetaDto": {
        "type": "object",
        "properties": {
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque string cursor pointing to the next page of results. null if there is no next page.",
            "example": "eyJpZCI6IjkxeFFlV3Z..."
          },
          "previous_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque string cursor pointing to the previous page of results. null if there is no previous page.",
            "example": "eyJpZCI6IjkxeFFlV3Z..."
          },
          "first_page_cursor": {
            "type": "string",
            "description": "Opaque string cursor pointing to the very first page in the entire dataset with respect to the current filter.",
            "example": "eyJpZCI6IjkxeFFlV3Z..."
          },
          "last_page_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque string cursor pointing to the very last page in the entire dataset with respect to the current filter.",
            "example": "eyJpZCI6IjkxeFFlV3Z..."
          },
          "total_count": {
            "type": "number",
            "nullable": true,
            "description": "Total number of results.",
            "example": 100
          },
          "page_number": {
            "type": "number",
            "description": "Current page number.",
            "example": 1
          }
        }
      },
      "MaliciousMetadata": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "On-chain address flagged as malicious or related"
          },
          "distance": {
            "type": "number",
            "description": "Distance in hops from the queried address (0 = directly malicious)"
          },
          "name_tag": {
            "type": "string",
            "description": "Known name tag or label for the address",
            "nullable": true
          },
          "entity": {
            "type": "string",
            "description": "Entity or organization associated with the address",
            "nullable": true
          },
          "category": {
            "type": "string",
            "description": "Category of malicious behavior (e.g. scam, exploit, mixer)",
            "nullable": true
          }
        },
        "required": [
          "address",
          "distance",
          "name_tag",
          "entity",
          "category"
        ]
      },
      "Attribution": {
        "type": "object",
        "properties": {
          "name_tag": {
            "type": "string",
            "description": "Name or label for the attributed address",
            "example": "Token Program"
          },
          "entity": {
            "type": "string",
            "description": "Entity or organization associated with the address",
            "example": "Solana"
          },
          "category": {
            "type": "string",
            "description": "Category of the attributed address",
            "example": "SYSTEM"
          },
          "address_role": {
            "type": "string",
            "description": "Role or function of the address",
            "example": "Program"
          }
        },
        "required": [
          "name_tag",
          "entity",
          "category",
          "address_role"
        ]
      },
      "RiskScore": {
        "type": "object",
        "properties": {
          "riskScore": {
            "type": "number",
            "nullable": true,
            "description": "Calculated normalized risk score (higher = riskier)",
            "example": 8
          },
          "riskLevel": {
            "enum": [
              "CRITICAL RISK (Directly malicious)",
              "Extremely high risk",
              "High risk",
              "Medium risk",
              "Low risk",
              "Very low risk"
            ],
            "type": "string",
            "description": "Human readable risk level classification"
          },
          "numHops": {
            "type": "number",
            "nullable": true,
            "description": "Minimum number of hops to the closest malicious address"
          },
          "maliciousAddressesFound": {
            "description": "List of malicious or related addresses discovered in the path",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/MaliciousMetadata"
            }
          },
          "reasoning": {
            "type": "string",
            "description": "Explanation of why the risk level/score was assigned"
          },
          "attribution": {
            "description": "Attribution information for known non-malicious addresses",
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/Attribution"
              }
            ]
          }
        },
        "required": [
          "riskScore",
          "riskLevel",
          "numHops",
          "maliciousAddressesFound",
          "reasoning"
        ]
      },
      "RiskFactorDetail": {
        "type": "object",
        "properties": {
          "level": {
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ],
            "type": "string",
            "description": "Risk level classification of this factor"
          },
          "explanation": {
            "type": "string",
            "description": "Explanation detailing why this factor has its assigned level"
          }
        },
        "required": [
          "level",
          "explanation"
        ]
      },
      "TokenInfo": {
        "type": "object",
        "properties": {
          "asset_address": {
            "type": "string",
            "description": "Asset identifier (Solana mint / EVM contract / Cosmos denom). Currently Solana mint.",
            "example": "So11111111111111111111111111111111111111112"
          },
          "name": {
            "type": "string",
            "description": "Token name",
            "example": "Wrapped SOL"
          },
          "symbol": {
            "type": "string",
            "description": "Ticker symbol",
            "example": "SOL"
          }
        },
        "required": [
          "asset_address",
          "name",
          "symbol"
        ]
      },
      "OverallAssessment": {
        "type": "object",
        "properties": {
          "risk_level": {
            "enum": [
              "LOW",
              "MEDIUM",
              "HIGH"
            ],
            "type": "string",
            "description": "Overall risk level derived from weighted factors"
          },
          "risk_score": {
            "type": "number",
            "description": "Aggregate risk score for the token"
          },
          "max_score": {
            "type": "number",
            "description": "Maximum theoretical score used for normalization"
          },
          "risk_percentage": {
            "type": "number",
            "description": "Percentage representation of the risk score (0-100)",
            "example": 72.5
          }
        },
        "required": [
          "risk_level",
          "risk_score",
          "max_score",
          "risk_percentage"
        ]
      },
      "Summary": {
        "type": "object",
        "properties": {
          "total_factors": {
            "type": "number",
            "description": "Total number of evaluated risk factors"
          },
          "high_risk_count": {
            "type": "number",
            "description": "Number of high risk factors"
          },
          "medium_risk_count": {
            "type": "number",
            "description": "Number of medium risk factors"
          },
          "low_risk_count": {
            "type": "number",
            "description": "Number of low risk factors"
          }
        },
        "required": [
          "total_factors",
          "high_risk_count",
          "medium_risk_count",
          "low_risk_count"
        ]
      },
      "TokenRiskResponse": {
        "type": "object",
        "properties": {
          "token_info": {
            "description": "Basic token identification details",
            "allOf": [
              {
                "$ref": "#/components/schemas/TokenInfo"
              }
            ]
          },
          "overall_assessment": {
            "description": "Overall risk assessment aggregation",
            "allOf": [
              {
                "$ref": "#/components/schemas/OverallAssessment"
              }
            ]
          },
          "summary": {
            "description": "Summary counts of risk factor severity levels",
            "allOf": [
              {
                "$ref": "#/components/schemas/Summary"
              }
            ]
          },
          "risk_factors": {
            "type": "object",
            "description": "Map of risk factor key to its detailed assessment",
            "additionalProperties": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/RiskFactorDetail"
                }
              ]
            }
          },
          "processing_time_ms": {
            "type": "number",
            "description": "Processing time in milliseconds for the assessment",
            "example": 154
          },
          "errors": {
            "description": "List of non-fatal errors encountered while computing the assessment",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "token_info",
          "overall_assessment",
          "summary",
          "risk_factors",
          "processing_time_ms",
          "errors"
        ]
      },
      "PaymentRiskFactor": {
        "type": "object",
        "properties": {
          "risk_context": {
            "enum": [
              "sender",
              "recipient",
              "interaction"
            ],
            "type": "string",
            "description": "Categorizes whether the risk is related to sender address only, recipient address only, or their interaction",
            "example": "recipient"
          },
          "factor": {
            "type": "string",
            "description": "Unique identifier for the risk factor",
            "example": "new_wallet_recipient"
          },
          "risk_level": {
            "enum": [
              "low",
              "medium",
              "high",
              "unknown"
            ],
            "type": "string",
            "description": "Risk level classification of this factor",
            "example": "medium"
          },
          "description": {
            "type": "string",
            "description": "Human-readable explanation of the risk factor",
            "example": "Recipient is a new wallet with minimal transaction history"
          }
        },
        "required": [
          "risk_context",
          "factor",
          "risk_level",
          "description"
        ]
      },
      "PaymentRequestSummary": {
        "type": "object",
        "properties": {
          "sender_address": {
            "type": "string",
            "description": "Sender blockchain address",
            "example": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          },
          "recipient_address": {
            "type": "string",
            "description": "Recipient blockchain address",
            "example": "7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi"
          },
          "amount": {
            "type": "number",
            "description": "Payment amount in USD equivalent",
            "example": 1000
          },
          "sender_network": {
            "type": "string",
            "description": "Sender blockchain network",
            "example": "solana"
          },
          "recipient_network": {
            "type": "string",
            "description": "Recipient blockchain network",
            "example": "solana"
          },
          "sender_token": {
            "type": "string",
            "nullable": true,
            "description": "Token/denom being sent (optional)"
          },
          "recipient_token": {
            "type": "string",
            "nullable": true,
            "description": "Token/denom being received (optional)"
          },
          "timestamp": {
            "type": "string",
            "nullable": true,
            "description": "Payment timestamp (optional)"
          }
        },
        "required": [
          "sender_address",
          "recipient_address",
          "amount",
          "sender_network",
          "recipient_network"
        ]
      },
      "PaymentRiskResponse": {
        "type": "object",
        "properties": {
          "overall_risk_level": {
            "enum": [
              "low",
              "medium",
              "high",
              "unknown"
            ],
            "type": "string",
            "description": "Overall risk level determined by maximum risk approach. Possible values: low, medium, high, unknown",
            "example": "high"
          },
          "risk_factors": {
            "description": "List of individual risk assessments performed",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentRiskFactor"
            }
          },
          "processing_time_ms": {
            "type": "number",
            "description": "Processing time in milliseconds",
            "example": 4159.017
          },
          "errors": {
            "description": "List of errors encountered during analysis (empty if no errors)",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "request_summary": {
            "description": "Echo of the original request parameters for verification",
            "allOf": [
              {
                "$ref": "#/components/schemas/PaymentRequestSummary"
              }
            ]
          }
        },
        "required": [
          "overall_risk_level",
          "risk_factors",
          "processing_time_ms",
          "errors",
          "request_summary"
        ]
      },
      "TokenBlacklistStatus": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Token symbol (USDT, USDC, CBBTC, USDP)",
            "example": "USDT"
          },
          "issuer": {
            "type": "string",
            "description": "Token issuer (Tether, Circle, Coinbase, Paxos)",
            "example": "Tether"
          },
          "is_currently_blacklisted": {
            "type": "boolean",
            "description": "Whether address is currently blacklisted by this token"
          },
          "first_blacklisted_date": {
            "type": "string",
            "description": "Date of first blacklist event (YYYY-MM-DD)",
            "example": "2023-12-09"
          },
          "last_event_date": {
            "type": "string",
            "description": "Date of most recent event",
            "example": "2023-12-09"
          },
          "last_event_type": {
            "type": "string",
            "description": "Type of most recent event",
            "enum": [
              "blacklist",
              "unblacklist"
            ]
          }
        },
        "required": [
          "token",
          "issuer",
          "is_currently_blacklisted"
        ]
      },
      "BlacklistEvent": {
        "type": "object",
        "properties": {
          "event_type": {
            "type": "string",
            "description": "Event type",
            "enum": [
              "blacklist",
              "unblacklist"
            ]
          },
          "token": {
            "type": "string",
            "description": "Token symbol",
            "example": "USDC"
          },
          "issuer": {
            "type": "string",
            "description": "Token issuer",
            "example": "Circle"
          },
          "network": {
            "type": "string",
            "description": "Blockchain network",
            "example": "ethereum"
          },
          "date": {
            "type": "string",
            "description": "Event date (YYYY-MM-DD)",
            "example": "2021-04-21"
          },
          "block_number": {
            "type": "number",
            "description": "Block number",
            "example": 12285873
          },
          "block_timestamp": {
            "type": "string",
            "description": "Block timestamp",
            "example": "2021-04-21 23:04:36"
          },
          "transaction_hash": {
            "type": "string",
            "description": "Transaction hash"
          },
          "token_account": {
            "type": "string",
            "description": "Token account address (Solana only)"
          }
        },
        "required": [
          "event_type",
          "token",
          "issuer",
          "network",
          "date"
        ]
      },
      "OFACSanctionInfo": {
        "type": "object",
        "properties": {
          "is_sanctioned": {
            "type": "boolean",
            "description": "Whether address is OFAC sanctioned"
          },
          "name_tag": {
            "type": "string",
            "description": "Name of sanctioned entity/individual",
            "example": "ANDREYEV, Anton Nikolaeyvich"
          },
          "category": {
            "type": "string",
            "description": "Category",
            "example": "OFAC Sanctioned"
          },
          "entity": {
            "type": "string",
            "description": "Entity name",
            "example": "OFAC"
          },
          "address_role": {
            "type": "string",
            "description": "Role type: Individual or Entity",
            "example": "Individual"
          },
          "first_sanctioned_date": {
            "type": "string",
            "description": "Date of sanction (YYYY-MM-DD)",
            "example": "2020-09-10"
          },
          "sanction_url": {
            "type": "string",
            "description": "URL to OFAC announcement",
            "example": "https://ofac.treasury.gov/recent-actions/20200910"
          }
        },
        "required": [
          "is_sanctioned"
        ]
      },
      "BlacklistAttribution": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name tag for the address",
            "example": "cbBTC Blacklisted Address (9b5a)"
          },
          "category": {
            "type": "string",
            "description": "Category",
            "example": "cbBTC Blacklist"
          },
          "role": {
            "type": "string",
            "description": "Address role",
            "example": "Blacklisted Address"
          },
          "entity": {
            "type": "string",
            "description": "Associated entity"
          },
          "tags": {
            "description": "Tags associated with the address",
            "example": [
              "BLACKLISTED",
              "STABLECOIN-ISSUER",
              "COMPLIANCE"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "malicious": {
            "type": "boolean",
            "description": "Whether marked as malicious"
          }
        }
      },
      "BlacklistCheckResponse": {
        "type": "object",
        "properties": {
          "address": {
            "type": "string",
            "description": "The queried blockchain address",
            "example": "0x1da5821544e25c636c1417ba96ade4cf6d2f9b5a"
          },
          "network": {
            "type": "string",
            "nullable": true,
            "description": "Network filter applied (null if all networks checked)",
            "example": "ethereum"
          },
          "is_token_blacklisted": {
            "type": "boolean",
            "description": "Whether address is currently blacklisted by any token issuer",
            "example": true
          },
          "is_ofac_sanctioned": {
            "type": "boolean",
            "description": "Whether address is on OFAC sanctions list",
            "example": false
          },
          "checked_at": {
            "type": "string",
            "description": "UTC timestamp when check was performed (ISO 8601)",
            "example": "2025-11-28T12:53:24Z"
          },
          "token_status_summary": {
            "nullable": true,
            "description": "Current blacklist status per token (when include_details=true)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TokenBlacklistStatus"
            }
          },
          "blacklist_event_history": {
            "nullable": true,
            "description": "Chronological list of blacklist/unblacklist events (when include_details=true)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BlacklistEvent"
            }
          },
          "ofac_info": {
            "nullable": true,
            "description": "OFAC sanction details (when sanctioned)",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/OFACSanctionInfo"
              }
            ]
          },
          "attribution": {
            "nullable": true,
            "description": "Known attribution/label for the address",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/BlacklistAttribution"
              }
            ]
          }
        },
        "required": [
          "address",
          "network",
          "is_token_blacklisted",
          "is_ofac_sanctioned",
          "checked_at"
        ]
      },
      "SimulateSolanaTxDto": {
        "type": "object",
        "properties": {
          "tx": {
            "type": "string",
            "minLength": 1,
            "description": "Encoded raw transaction (base64 or base58)",
            "example": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAMFEJeb5qTc67efsgZI7ONZ7zVxpO4dt1RQdJUXALHbMrqWD8daOMRtjpRGL/NJrFK4+dloWCuEb9yNAU0iiTXfswbd9uHXZaGT2cvhRs7reawctIXtX1s3kTqM9YV+/wCpHONZ7VoBLgT6FCucdRocXofP0KAWG5yF/9MbeM382PbG+nrzvtutOj1l82qryXQxsbvkwtL24OR8pgIDRS9dYQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwIDAQMACQQA5AtUAgAAAAIEAQQDAAoNAOQLVAIAAAAGAgIBAAEF"
          },
          "encoding_type": {
            "enum": [
              "base64",
              "base58"
            ],
            "type": "string",
            "description": "Encoding type of the transaction",
            "example": "base64"
          }
        },
        "required": [
          "tx",
          "encoding_type"
        ]
      },
      "SimulateTxDto": {
        "type": "object",
        "properties": {
          "tx": {
            "type": "string",
            "minLength": 1,
            "description": "Keplr transaction or Base64 encoded raw transaction",
            "example": "CoEECv4DCh0vY29zbW9zLmF1dGh6LnYxYmV0YTEuTXNnRXhlYxLcAworb3NtbzE3OW50bGM3c2gyZGFkc2F0ZjdoNGd6ZHkzand2cTQ3NWE3ZWN0NxKsAwoxL29zbW9zaXMucG9vbG1hbmFnZXIudjFiZXRhMS5Nc2dTd2FwRXhhY3RBbW91bnRJbhL2Agorb3NtbzFkbGRyeHo1cDh1ZXp4ejNxc3RwdjkyZGU3d2dmcDdodnI3MmRjbRJJCOMLEkRpYmMvMTc4MjQ4QzI2MkRFMkUxNDFFRTYyODdFRTdBQjA4NTRGMDVGMjVCMEEzRjQwQzRCOTEyRkExQzdFNTFGNDY2RRIKCJQNEgV1b3NtbxJJCLgLEkRpYmMvNDk4QTA3NTFDNzk4QTBEOUEzODlBQTM2OTExMjNEQURBNTdEQUE0RkUxNjVENUM3NTg5NDUwNUI4NzZCQTZFNBJJCMcJEkRpYmMvRDE4OTMzNUM2RTRBNjhCNTEzQzEwQUIyMjdCRjFDMUQzOEM3NDY3NjYyNzhCQTNFRUI0RkIxNDEyNEYxRDg1OBpQCkRpYmMvNDk4QTA3NTFDNzk4QTBEOUEzODlBQTM2OTExMjNEQURBNTdEQUE0RkUxNjVENUM3NTg5NDUwNUI4NzZCQTZFNBIINTMwNzIzNTUiCDUzMDcyMzU1EmkKUgpGCh8vY29zbW9zLmNyeXB0by5zZWNwMjU2azEuUHViS2V5EiMKIQI44AflBFsxuMDrOXsYpll6ZdyZB4hvIgVmAV9y7inkcBIECgIIARiH4B0SEwoNCgV1b3NtbxIENDM3NhDw52oaQNcdpT1IJzCdk1gfBY3z7r+ArcRMHtCJrxf5J0O3B8suIti4rDlIWpedzw0GoJx/VQvaM6ZT44Fh8bMh9O6IWBw="
          }
        },
        "required": [
          "tx"
        ]
      },
      "GasInfo": {
        "type": "object",
        "properties": {
          "gas_wanted": {
            "type": "string"
          },
          "gas_used": {
            "type": "string"
          }
        },
        "required": [
          "gas_wanted",
          "gas_used"
        ]
      },
      "SimulatedTx": {
        "type": "object",
        "properties": {
          "addresses": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "gas_info": {
            "$ref": "#/components/schemas/GasInfo"
          }
        },
        "required": [
          "addresses",
          "gas_info"
        ]
      },
      "AttributionSignalResultDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "sanctions_ofac"
          },
          "severity": {
            "type": "string",
            "example": "severe",
            "enum": [
              "severe",
              "high",
              "medium",
              "low"
            ]
          },
          "result": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "signal",
          "severity",
          "result"
        ]
      },
      "AttributionSummaryDto": {
        "type": "object",
        "properties": {
          "triggered": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttributionSignalResultDto"
            }
          }
        },
        "required": [
          "triggered"
        ]
      },
      "ExposureSignalResultDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "compliance-risk"
          },
          "mode": {
            "type": "string",
            "example": "percentage",
            "enum": [
              "percentage"
            ]
          },
          "result": {
            "type": "boolean",
            "example": true
          },
          "percentage": {
            "type": "string",
            "example": "42.30%",
            "description": "Exposed bucket volume as a share of total counterparty volume, formatted human-readable."
          },
          "summary": {
            "type": "string",
            "example": "42.30% of counterparty volume is compliance-risk, crossing the 5% (high) threshold.",
            "description": "Human-readable explanation of why this signal fired."
          }
        },
        "required": [
          "signal",
          "mode",
          "result",
          "percentage",
          "summary"
        ]
      },
      "ExposureSummaryDto": {
        "type": "object",
        "properties": {
          "triggered": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExposureSignalResultDto"
            }
          }
        },
        "required": [
          "triggered"
        ]
      },
      "BehaviourSignalResultDto": {
        "type": "object",
        "properties": {
          "behaviour": {
            "type": "string",
            "example": "smurfing"
          },
          "severity": {
            "type": "string",
            "example": "high",
            "enum": [
              "severe",
              "high",
              "medium",
              "low"
            ]
          },
          "confidence": {
            "type": "number",
            "example": 0.78,
            "minimum": 0,
            "maximum": 1
          }
        },
        "required": [
          "behaviour",
          "severity",
          "confidence"
        ]
      },
      "BehaviourSummaryDto": {
        "type": "object",
        "properties": {
          "detected": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BehaviourSignalResultDto"
            }
          }
        },
        "required": [
          "detected"
        ]
      },
      "ScreenMetaDto": {
        "type": "object",
        "properties": {
          "es_attribution_ms": {
            "type": "number",
            "example": 120
          },
          "config_ms": {
            "type": "number",
            "example": 5
          },
          "ch_counterparties_ms": {
            "type": "number",
            "example": 340
          },
          "ch_totals_ms": {
            "type": "number",
            "example": 80
          },
          "es_interchain_ms": {
            "type": "number",
            "example": 210
          },
          "helius_ms": {
            "type": "number",
            "example": 150
          },
          "features_redis_ms": {
            "type": "number",
            "example": 60
          },
          "counterparty_attribution_ms": {
            "type": "number",
            "example": 0
          },
          "parallel_ms": {
            "type": "number",
            "example": 350
          },
          "total_ms": {
            "type": "number",
            "example": 410
          }
        },
        "required": [
          "es_attribution_ms",
          "config_ms",
          "ch_counterparties_ms",
          "ch_totals_ms",
          "es_interchain_ms",
          "helius_ms",
          "features_redis_ms",
          "counterparty_attribution_ms",
          "parallel_ms",
          "total_ms"
        ]
      },
      "RiskAssessmentDto": {
        "type": "object",
        "properties": {
          "screen_id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "address": {
            "type": "string",
            "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28"
          },
          "address_active_on": {
            "example": [
              "ethereum",
              "polygon"
            ],
            "description": "Networks this address has labelled activity on (from addresses.labels).",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total_incoming_usd": {
            "type": "number",
            "example": 1842300.45,
            "description": "All-counterparty incoming USD volume (lifetime). 0 for unsupported networks."
          },
          "total_outgoing_usd": {
            "type": "number",
            "example": 1798450.12,
            "description": "All-counterparty outgoing USD volume (lifetime)."
          },
          "malicious_incoming_usd": {
            "type": "number",
            "example": 184500,
            "description": "USD volume from counterparties tagged as malicious."
          },
          "malicious_outgoing_usd": {
            "type": "number",
            "example": 92300,
            "description": "USD volume to counterparties tagged as malicious."
          },
          "severity": {
            "type": "string",
            "example": "high",
            "enum": [
              "severe",
              "high",
              "medium",
              "low",
              "none"
            ],
            "description": "Worst individual signal severity across all three pillars."
          },
          "attribution": {
            "$ref": "#/components/schemas/AttributionSummaryDto"
          },
          "exposure": {
            "$ref": "#/components/schemas/ExposureSummaryDto"
          },
          "behaviour": {
            "$ref": "#/components/schemas/BehaviourSummaryDto"
          },
          "timestamp": {
            "type": "string",
            "example": "2026-05-04T14:30:00Z"
          },
          "meta": {
            "description": "Per-upstream-call latency (ms) for this screen.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ScreenMetaDto"
              }
            ]
          },
          "evidence": {
            "type": "object",
            "description": "Present only when `include_evidence=true`. Same shape as GET /v2/risk/evidence/:screenId minus the wrapping screen_id."
          }
        },
        "required": [
          "screen_id",
          "address",
          "address_active_on",
          "total_incoming_usd",
          "total_outgoing_usd",
          "malicious_incoming_usd",
          "malicious_outgoing_usd",
          "severity",
          "attribution",
          "exposure",
          "behaviour",
          "timestamp",
          "meta"
        ]
      },
      "BatchMetaDto": {
        "type": "object",
        "properties": {
          "total": {
            "type": "number",
            "example": 5
          },
          "scored": {
            "type": "number",
            "example": 5
          },
          "errors": {
            "type": "number",
            "example": 0
          }
        },
        "required": [
          "total",
          "scored",
          "errors"
        ]
      },
      "BatchRiskAssessmentDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RiskAssessmentDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/BatchMetaDto"
          }
        },
        "required": [
          "items",
          "meta"
        ]
      },
      "HistoryItemDto": {
        "type": "object",
        "properties": {
          "screen_id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "address": {
            "type": "string",
            "example": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28"
          },
          "address_active_on": {
            "example": [
              "ethereum",
              "polygon"
            ],
            "description": "Networks this address has labelled activity on (from addresses.labels).",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "total_incoming_usd": {
            "type": "number",
            "example": 1842300.45,
            "description": "All-counterparty incoming USD volume (lifetime). 0 for unsupported networks."
          },
          "total_outgoing_usd": {
            "type": "number",
            "example": 1798450.12,
            "description": "All-counterparty outgoing USD volume (lifetime)."
          },
          "malicious_incoming_usd": {
            "type": "number",
            "example": 184500,
            "description": "USD volume from counterparties tagged as malicious."
          },
          "malicious_outgoing_usd": {
            "type": "number",
            "example": 92300,
            "description": "USD volume to counterparties tagged as malicious."
          },
          "severity": {
            "type": "string",
            "example": "high",
            "enum": [
              "severe",
              "high",
              "medium",
              "low",
              "none"
            ],
            "description": "Worst individual signal severity across all three pillars."
          },
          "attribution": {
            "$ref": "#/components/schemas/AttributionSummaryDto"
          },
          "exposure": {
            "$ref": "#/components/schemas/ExposureSummaryDto"
          },
          "behaviour": {
            "$ref": "#/components/schemas/BehaviourSummaryDto"
          },
          "timestamp": {
            "type": "string",
            "example": "2026-05-04T14:30:00Z"
          },
          "meta": {
            "description": "Per-upstream-call latency (ms) for this screen.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ScreenMetaDto"
              }
            ]
          },
          "evidence": {
            "type": "object",
            "description": "Present only when `include_evidence=true`. Same shape as GET /v2/risk/evidence/:screenId minus the wrapping screen_id."
          }
        },
        "required": [
          "screen_id",
          "address",
          "address_active_on",
          "total_incoming_usd",
          "total_outgoing_usd",
          "malicious_incoming_usd",
          "malicious_outgoing_usd",
          "severity",
          "attribution",
          "exposure",
          "behaviour",
          "timestamp",
          "meta"
        ]
      },
      "HistoryMetadataDto": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "number",
            "example": 10,
            "description": "Page size (fixed at 10)."
          },
          "offset": {
            "type": "number",
            "example": 0
          },
          "total": {
            "type": "number",
            "example": 1234,
            "description": "Total successful screenings for this workspace."
          }
        },
        "required": [
          "limit",
          "offset",
          "total"
        ]
      },
      "HistoryResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HistoryItemDto"
            }
          },
          "metadata": {
            "$ref": "#/components/schemas/HistoryMetadataDto"
          }
        },
        "required": [
          "items",
          "metadata"
        ]
      },
      "EvidenceDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "example": "counterparty",
            "enum": [
              "transaction",
              "counterparty",
              "pattern",
              "attribution"
            ]
          },
          "summary": {
            "type": "string",
            "example": "Interacted with OFAC-sanctioned address 0xDEF... on 2026-03-15"
          },
          "details": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "address": "0xDEF...",
              "tx_hash": "0x789...",
              "timestamp": "2026-03-15T14:22:00Z",
              "entity": "Tornado Cash",
              "list": "OFAC SDN"
            }
          }
        },
        "required": [
          "type",
          "summary",
          "details"
        ]
      },
      "AttributionEvidenceEntryDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "sanctions_ofac"
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EvidenceDto"
            }
          }
        },
        "required": [
          "signal",
          "evidence"
        ]
      },
      "ExposureEvidenceEntryDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "obfuscation"
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EvidenceDto"
            }
          }
        },
        "required": [
          "signal",
          "evidence"
        ]
      },
      "BehaviourEvidenceEntryDto": {
        "type": "object",
        "properties": {
          "behaviour": {
            "type": "string",
            "example": "smurfing"
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EvidenceDto"
            }
          }
        },
        "required": [
          "behaviour",
          "evidence"
        ]
      },
      "EvidenceResponseDto": {
        "type": "object",
        "properties": {
          "screen_id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "assessment": {
            "$ref": "#/components/schemas/RiskAssessmentDto"
          },
          "attribution_evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttributionEvidenceEntryDto"
            }
          },
          "exposure_evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExposureEvidenceEntryDto"
            }
          },
          "behaviour_evidence": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BehaviourEvidenceEntryDto"
            }
          }
        },
        "required": [
          "screen_id",
          "assessment",
          "attribution_evidence",
          "exposure_evidence",
          "behaviour_evidence"
        ]
      },
      "AttributionConfigDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "sanctions_ofac"
          },
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "severity": {
            "type": "string",
            "enum": [
              "severe",
              "high",
              "medium",
              "low"
            ],
            "example": "severe"
          }
        },
        "required": [
          "signal",
          "enabled",
          "severity"
        ]
      },
      "SeverityThresholdsMapDto": {
        "type": "object",
        "properties": {
          "low": {
            "type": "number",
            "minimum": 0,
            "example": 0.01
          },
          "medium": {
            "type": "number",
            "minimum": 0,
            "example": 0.05
          },
          "high": {
            "type": "number",
            "minimum": 0,
            "example": 0.2
          },
          "severe": {
            "type": "number",
            "minimum": 0,
            "example": 0.5
          }
        },
        "required": [
          "low",
          "medium",
          "high",
          "severe"
        ]
      },
      "ExposureConfigDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "obfuscation"
          },
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "thresholds": {
            "description": "Maps observed exposure fraction (0-1) to severity.",
            "allOf": [
              {
                "$ref": "#/components/schemas/SeverityThresholdsMapDto"
              }
            ]
          },
          "floor_usd": {
            "type": "number",
            "minimum": 0,
            "example": 1000,
            "description": "Minimum exposed USD required for the signal to fire even when the exposure % threshold is met. Defaults to 0 when omitted."
          }
        },
        "required": [
          "signal",
          "enabled",
          "thresholds"
        ]
      },
      "BehaviourConfigDto": {
        "type": "object",
        "properties": {
          "behaviour": {
            "type": "string",
            "example": "smurfing"
          },
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "thresholds": {
            "description": "Maps detection confidence (0-1) to severity. Below low threshold = none.",
            "allOf": [
              {
                "$ref": "#/components/schemas/SeverityThresholdsMapDto"
              }
            ]
          },
          "ignore": {
            "type": "boolean",
            "example": false,
            "description": "Detect but do not include in severity determination"
          }
        },
        "required": [
          "behaviour",
          "enabled",
          "thresholds",
          "ignore"
        ]
      },
      "RiskConfigSpecDto": {
        "type": "object",
        "properties": {
          "workspace_id": {
            "type": "string",
            "example": "ws-12345"
          },
          "attribution_signals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AttributionConfigDto"
            }
          },
          "exposure_signals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExposureConfigDto"
            }
          },
          "behaviours": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BehaviourConfigDto"
            }
          },
          "updated_at": {
            "type": "string",
            "example": "2026-05-18T10:00:00Z"
          }
        },
        "required": [
          "workspace_id",
          "attribution_signals",
          "exposure_signals",
          "behaviours",
          "updated_at"
        ]
      },
      "PatchAttributionConfigDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "severity": {
            "type": "object",
            "enum": [
              "severe",
              "high",
              "medium",
              "low"
            ]
          }
        },
        "required": [
          "signal"
        ]
      },
      "PatchExposureConfigDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "thresholds": {
            "$ref": "#/components/schemas/SeverityThresholdsMapDto"
          },
          "floor_usd": {
            "type": "number",
            "minimum": 0
          }
        },
        "required": [
          "signal"
        ]
      },
      "PatchBehaviourConfigDto": {
        "type": "object",
        "properties": {
          "behaviour": {
            "type": "string"
          },
          "enabled": {
            "type": "boolean"
          },
          "thresholds": {
            "$ref": "#/components/schemas/SeverityThresholdsMapDto"
          },
          "ignore": {
            "type": "boolean"
          }
        },
        "required": [
          "behaviour"
        ]
      },
      "PatchRiskConfigDto": {
        "type": "object",
        "properties": {
          "attribution_signals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PatchAttributionConfigDto"
            }
          },
          "exposure_signals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PatchExposureConfigDto"
            }
          },
          "behaviours": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PatchBehaviourConfigDto"
            }
          },
          "attribution_removals": {
            "description": "Signal ids to remove from attribution_signals.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "exposure_removals": {
            "description": "Exposure signal ids to remove.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "behaviour_removals": {
            "description": "Behaviour ids to remove.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "SignalMetaDto": {
        "type": "object",
        "properties": {
          "signal": {
            "type": "string",
            "example": "ofac-sanctioned"
          },
          "name": {
            "type": "string",
            "example": "OFAC Sanctioned"
          }
        },
        "required": [
          "signal",
          "name"
        ]
      },
      "BehaviourMetaDto": {
        "type": "object",
        "properties": {
          "behaviour": {
            "type": "string",
            "example": "chain-peeling"
          },
          "description": {
            "type": "string",
            "example": "Funds moved through series of wallets, small amounts skimmed per hop"
          },
          "default_severity": {
            "type": "string",
            "example": "high",
            "enum": [
              "severe",
              "high",
              "medium",
              "low"
            ]
          },
          "default_thresholds": {
            "description": "Suggested confidence-to-severity mapping.",
            "allOf": [
              {
                "$ref": "#/components/schemas/SeverityThresholdsMapDto"
              }
            ]
          },
          "priority": {
            "type": "string",
            "example": "v2",
            "enum": [
              "v2",
              "future"
            ]
          },
          "example": {
            "type": "string",
            "example": "$100k -> $85k -> $70k -> $55k -> $40k across 5 addresses"
          }
        },
        "required": [
          "behaviour",
          "description",
          "default_severity",
          "default_thresholds",
          "priority",
          "example"
        ]
      },
      "SignalsCatalogueDto": {
        "type": "object",
        "properties": {
          "signals": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SignalMetaDto"
            }
          },
          "behaviours": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BehaviourMetaDto"
            }
          }
        },
        "required": [
          "signals",
          "behaviours"
        ]
      },
      "AlertChannelListItemDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "workspace_id": {
            "type": "string",
            "example": "workspace-123"
          },
          "name": {
            "type": "string",
            "example": "My Slack Channel"
          },
          "type": {
            "enum": [
              "slack",
              "telegram",
              "discord",
              "webhook",
              "pagerduty",
              "email",
              "incidentio"
            ],
            "type": "string",
            "example": "slack"
          },
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "connected": {
            "type": "boolean",
            "description": "Whether the channel is ready to receive deliveries. Always true except for a telegram channel that has not yet linked a chat.",
            "example": true
          },
          "created_at": {
            "type": "string",
            "example": "2026-05-14T12:00:00.000Z"
          },
          "params": {
            "type": "object",
            "description": "Type-specific params surfaced in list items. Present only for telegram channels, carrying the registration `unique_code`.",
            "additionalProperties": true,
            "example": {
              "unique_code": "abc123"
            }
          }
        },
        "required": [
          "id",
          "workspace_id",
          "name",
          "type",
          "enabled",
          "connected",
          "created_at"
        ]
      },
      "ListAlertChannelsResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertChannelListItemDto"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "CreateAlertChannelDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Display name for the channel.",
            "example": "My Slack Channel"
          },
          "type": {
            "enum": [
              "slack",
              "telegram",
              "discord",
              "webhook",
              "pagerduty",
              "email",
              "incidentio"
            ],
            "type": "string",
            "description": "Channel delivery type.",
            "example": "slack"
          },
          "params": {
            "type": "object",
            "description": "Type-specific parameters. Slack, Discord, and generic webhooks require webhook_url. PagerDuty requires routing_key. Email requires recipients (array of addresses). incident.io requires url and token. Telegram is generated server-side.",
            "additionalProperties": true,
            "example": {
              "webhook_url": "https://hooks.slack.com/services/T00/B00/xxxx"
            }
          }
        },
        "required": [
          "name",
          "type"
        ]
      },
      "AlertChannelDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "workspace_id": {
            "type": "string",
            "example": "workspace-123"
          },
          "name": {
            "type": "string",
            "example": "My Slack Channel"
          },
          "type": {
            "enum": [
              "slack",
              "telegram",
              "discord",
              "webhook",
              "pagerduty",
              "email",
              "incidentio"
            ],
            "type": "string",
            "example": "slack"
          },
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "connected": {
            "type": "boolean",
            "description": "Whether the channel is ready to receive deliveries. Always true except for a telegram channel that has not yet linked a chat.",
            "example": true
          },
          "created_at": {
            "type": "string",
            "example": "2026-05-14T12:00:00.000Z"
          },
          "params": {
            "type": "object",
            "description": "Type-specific channel parameters.",
            "additionalProperties": true,
            "example": {
              "webhook_url": "https://hooks.slack.com/services/T00/B00/xxxx"
            }
          },
          "deleted_at": {
            "type": "string",
            "nullable": true,
            "description": "Soft-delete timestamp. Null while the channel is active.",
            "example": null
          },
          "updated_at": {
            "type": "string",
            "example": "2026-05-14T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "workspace_id",
          "name",
          "type",
          "enabled",
          "connected",
          "created_at",
          "updated_at"
        ]
      },
      "DeleteAlertChannelResponseDto": {
        "type": "object",
        "properties": {
          "acknowledged": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "acknowledged"
        ]
      },
      "ChannelDataDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "Primary Slack Channel"
          },
          "type": {
            "enum": [
              "slack",
              "telegram",
              "discord",
              "webhook",
              "pagerduty",
              "email",
              "incidentio"
            ],
            "type": "string",
            "example": "slack"
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "webhook_url": "https://hooks.slack.com/services/T00/B00/xxxx"
            }
          },
          "enabled": {
            "type": "boolean",
            "example": false
          }
        }
      },
      "ChannelOperationDto": {
        "type": "object",
        "properties": {
          "action": {
            "type": "string",
            "enum": [
              "add",
              "update",
              "remove"
            ],
            "example": "add"
          },
          "channel": {
            "$ref": "#/components/schemas/ChannelDataDto"
          }
        },
        "required": [
          "action",
          "channel"
        ]
      },
      "UpdateChannelsDto": {
        "type": "object",
        "properties": {
          "operations": {
            "minItems": 1,
            "maxItems": 1000,
            "example": [
              {
                "action": "add",
                "channel": {
                  "name": "Primary Slack Channel",
                  "type": "slack",
                  "params": {
                    "webhook_url": "https://hooks.slack.com/services/T00/B00/xxxx"
                  }
                }
              },
              {
                "action": "update",
                "channel": {
                  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                  "name": "Renamed Channel",
                  "enabled": false
                }
              },
              {
                "action": "remove",
                "channel": {
                  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                }
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChannelOperationDto"
            }
          }
        },
        "required": [
          "operations"
        ]
      },
      "UpdateChannelsResponseDto": {
        "type": "object",
        "properties": {
          "acknowledged": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "acknowledged"
        ]
      },
      "TemplateVariantDto": {
        "type": "object",
        "properties": {
          "network": {
            "type": "string",
            "description": "Network slug for this variant.",
            "example": "eth"
          },
          "template_id": {
            "type": "string",
            "description": "Template id to create a rule / fetch the form for this network.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "format": "uuid"
          }
        },
        "required": [
          "network",
          "template_id"
        ]
      },
      "TemplateGroupDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "description": "Internal rule type identifier used by the alert engine.",
            "example": "SafeMultisigExecution"
          },
          "label": {
            "type": "string",
            "description": "Short display name.",
            "example": "Safe Multisig Tx Executed"
          },
          "description": {
            "type": "string",
            "description": "Message shown when the rule fires.",
            "example": "A large transfer was detected on {{network}}"
          },
          "severity": {
            "type": "string",
            "description": "Risk severity.",
            "example": "high"
          },
          "tags": {
            "example": [
              "safe",
              "multisig"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "networks": {
            "example": [
              "arb1",
              "bnb",
              "eth",
              "pol"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "templates": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateVariantDto"
            }
          }
        },
        "required": [
          "type",
          "label",
          "description",
          "severity",
          "tags",
          "networks",
          "templates"
        ]
      },
      "AlertTemplateListMetaDto": {
        "type": "object",
        "properties": {
          "networks": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "networks"
        ]
      },
      "ListAlertTemplatesResponseDto": {
        "type": "object",
        "properties": {
          "groups": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TemplateGroupDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/AlertTemplateListMetaDto"
          }
        },
        "required": [
          "groups",
          "meta"
        ]
      },
      "RuleParameterDto": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "Human-readable label for this parameter.",
            "example": "Wallet"
          },
          "description": {
            "type": "string",
            "description": "Description of what value to provide.",
            "example": "The address to monitor"
          },
          "field": {
            "type": "string",
            "description": "Field key used when creating an alert rule from this template.",
            "example": "address"
          },
          "field_type": {
            "type": "string",
            "description": "Expected value type (e.g. \"Address\", \"Amount\").",
            "example": "Address"
          },
          "optional": {
            "type": "boolean",
            "description": "Whether this parameter is optional.",
            "example": false
          }
        },
        "required": [
          "label",
          "description",
          "field",
          "field_type",
          "optional"
        ]
      },
      "AlertTemplateDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the alert rule template.",
            "example": "1"
          },
          "type": {
            "type": "string",
            "description": "Internal rule type identifier used by the alert engine.",
            "example": "large_transfer"
          },
          "label": {
            "type": "string",
            "description": "Short display name for the template.",
            "example": "Large Transfer"
          },
          "description": {
            "type": "string",
            "description": "Message template sent when the rule fires. Supports `{{variable}}` placeholders.",
            "example": "A large transfer was detected on {{network}}"
          },
          "network": {
            "type": "string",
            "description": "Network slug this template targets.",
            "example": "eth"
          },
          "severity": {
            "type": "string",
            "description": "Risk severity of alerts produced by this template.",
            "example": "high",
            "enum": [
              "low",
              "medium",
              "high"
            ]
          },
          "tags": {
            "description": "Categorisation tags for filtering and discovery.",
            "example": [
              "defi",
              "transfer"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "trigger": {
            "type": "string",
            "description": "Whether the template is evaluated per block or per tick.",
            "enum": [
              "BLOCK",
              "TICK"
            ],
            "example": "BLOCK"
          },
          "parameters": {
            "description": "Parameters the user must supply when creating an alert rule from this template.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RuleParameterDto"
            }
          }
        },
        "required": [
          "id",
          "type",
          "label",
          "description",
          "network",
          "severity",
          "tags",
          "trigger",
          "parameters"
        ]
      },
      "AlertEventListItemDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the alert event.",
            "example": "clxyz1234abcd"
          },
          "time": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the on-chain event occurred.",
            "example": "2026-05-10T14:22:00.000Z"
          },
          "tx_hash": {
            "type": "string",
            "nullable": true,
            "description": "Transaction hash associated with the event.",
            "example": "0xabc123...def456"
          },
          "block_number": {
            "type": "number",
            "nullable": true,
            "description": "Block number at which the event was detected.",
            "example": 19823401
          },
          "network": {
            "type": "string",
            "description": "Network slug where the event occurred.",
            "example": "ethereum"
          },
          "alert_rule_id": {
            "type": "string",
            "nullable": true,
            "description": "ID of the alert rule that produced this event.",
            "example": "7890123456789012"
          },
          "addresses_involved": {
            "description": "List of blockchain addresses involved in the event.",
            "example": [
              "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the event record was created.",
            "example": "2026-05-10T14:22:05.000Z"
          },
          "details": {
            "type": "object",
            "description": "Arbitrary structured data specific to the event type.",
            "example": {
              "amount": 5000000,
              "token": "USDC",
              "from": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28",
              "to": "0xAbC...123"
            }
          },
          "severity": {
            "type": "string",
            "description": "Risk severity of the event.",
            "example": "high",
            "enum": [
              "low",
              "medium",
              "high"
            ]
          },
          "caption": {
            "type": "string",
            "description": "Human-readable caption describing the event.",
            "example": "Large USDC transfer detected"
          }
        },
        "required": [
          "id",
          "time",
          "network",
          "addresses_involved",
          "created_at",
          "details",
          "severity",
          "caption"
        ]
      },
      "ListAlertEventsResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertEventListItemDto"
            }
          },
          "meta": {
            "$ref": "#/components/schemas/CursorMetaDto"
          }
        },
        "required": [
          "items",
          "meta"
        ]
      },
      "AlertEventDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the alert event.",
            "example": "clxyz1234abcd"
          },
          "time": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the on-chain event occurred.",
            "example": "2026-05-10T14:22:00.000Z"
          },
          "tx_hash": {
            "type": "string",
            "nullable": true,
            "description": "Transaction hash associated with the event.",
            "example": "0xabc123...def456"
          },
          "block_number": {
            "type": "number",
            "nullable": true,
            "description": "Block number at which the event was detected.",
            "example": 19823401
          },
          "network": {
            "type": "string",
            "description": "Network slug where the event occurred.",
            "example": "ethereum"
          },
          "alert_rule_id": {
            "type": "string",
            "nullable": true,
            "description": "ID of the alert rule that produced this event.",
            "example": "7890123456789012"
          },
          "addresses_involved": {
            "description": "List of blockchain addresses involved in the event.",
            "example": [
              "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "description": "ISO 8601 timestamp of when the event record was created.",
            "example": "2026-05-10T14:22:05.000Z"
          },
          "details": {
            "type": "object",
            "description": "Arbitrary structured data specific to the event type.",
            "example": {
              "amount": 5000000,
              "token": "USDC",
              "from": "0x742d35Cc6634C0532925a3b844Bc9e7595f2bD28",
              "to": "0xAbC...123"
            }
          },
          "severity": {
            "type": "string",
            "description": "Risk severity of the event.",
            "example": "high",
            "enum": [
              "low",
              "medium",
              "high"
            ]
          },
          "caption": {
            "type": "string",
            "description": "Human-readable caption describing the event.",
            "example": "Large USDC transfer detected"
          },
          "access_type": {
            "type": "string",
            "description": "Caller's access relationship to this event.",
            "example": "same",
            "enum": [
              "global",
              "same",
              "diff",
              "none"
            ]
          }
        },
        "required": [
          "id",
          "time",
          "network",
          "addresses_involved",
          "created_at",
          "details",
          "severity",
          "caption",
          "access_type"
        ]
      },
      "SubscribedChannelDto": {
        "type": "object",
        "properties": {
          "alert_channel_id": {
            "type": "string",
            "example": "44444444-4444-4444-4444-444444444445"
          },
          "min_severity": {
            "nullable": true,
            "enum": [
              "info",
              "low",
              "medium",
              "high",
              "critical"
            ],
            "type": "string",
            "example": null
          }
        },
        "required": [
          "alert_channel_id"
        ]
      },
      "AlertRuleDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "workspace_id": {
            "type": "string",
            "example": "workspace-123"
          },
          "name": {
            "type": "string",
            "nullable": true,
            "example": "High gas on eth"
          },
          "rule_type": {
            "type": "string",
            "example": "GasPressure"
          },
          "network": {
            "type": "string",
            "nullable": true,
            "example": "eth"
          },
          "severity": {
            "type": "string",
            "example": "high"
          },
          "parameters": {
            "type": "object",
            "additionalProperties": true,
            "example": {
              "threshold": 90
            }
          },
          "trigger": {
            "type": "string",
            "enum": [
              "BLOCK",
              "TICK"
            ],
            "example": "BLOCK"
          },
          "enabled": {
            "type": "boolean",
            "example": true
          },
          "version": {
            "type": "number",
            "description": "Incremented each time the rule parameters change. Starts at 1.",
            "example": 1
          },
          "subscribed_channels": {
            "example": [
              {
                "alert_channel_id": "44444444-4444-4444-4444-444444444445",
                "min_severity": null
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SubscribedChannelDto"
            }
          },
          "runner_id": {
            "type": "string",
            "nullable": true,
            "example": "alert-runner-eth-v2"
          },
          "created_at": {
            "type": "string",
            "example": "2026-05-14T12:00:00.000Z"
          },
          "updated_at": {
            "type": "string",
            "example": "2026-05-14T12:00:00.000Z"
          },
          "alert_template": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/AlertTemplateDto"
              }
            ]
          }
        },
        "required": [
          "id",
          "workspace_id",
          "rule_type",
          "severity",
          "parameters",
          "trigger",
          "enabled",
          "version",
          "subscribed_channels",
          "created_at",
          "updated_at"
        ]
      },
      "ListAlertRulesResponseDto": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertRuleDto"
            }
          }
        },
        "required": [
          "items"
        ]
      },
      "CreateAlertRuleDto": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the template this rule instantiates. The template supplies the rule_type, network, runner_id, severity, and trigger.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Display name for the rule.",
            "example": "High gas on eth"
          },
          "severity": {
            "type": "string",
            "maxLength": 255,
            "description": "Severity override. Defaults to the matched template severity.",
            "example": "high"
          },
          "parameters": {
            "type": "object",
            "description": "User-supplied parameter values, as a `{ field: value }` object. A `[{ field, value }]` array or single-element wrapper is also accepted and normalized to an object on write.",
            "additionalProperties": true
          },
          "trigger": {
            "type": "string",
            "description": "Trigger override. Defaults to the matched template trigger.",
            "enum": [
              "BLOCK",
              "TICK"
            ]
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "PatchAlertRuleDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Display name for the rule.",
            "example": "High gas on eth"
          },
          "severity": {
            "type": "string",
            "maxLength": 255,
            "description": "Severity label for the rule.",
            "example": "high"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether the rule is enabled.",
            "example": true
          },
          "parameters": {
            "type": "object",
            "description": "Replacement parameter values, as a `{ field: value }` object (arrays are normalized to an object on write). Changing this bumps the rule's version and archives the previous version.",
            "additionalProperties": true
          }
        }
      },
      "RuleChannelLinkDto": {
        "type": "object",
        "properties": {
          "alert_channel_id": {
            "type": "string",
            "format": "uuid",
            "description": "An alert_channels id in the caller workspace.",
            "example": "44444444-4444-4444-4444-444444444445"
          },
          "min_severity": {
            "enum": [
              "info",
              "low",
              "medium",
              "high",
              "critical"
            ],
            "type": "string",
            "description": "Minimum severity delivered to this destination for this rule. Omit (or null) for no floor — every alert is delivered. When set, only alerts of equal or higher severity are delivered.",
            "nullable": true
          }
        },
        "required": [
          "alert_channel_id"
        ]
      },
      "LinkRuleChannelsDto": {
        "type": "object",
        "properties": {
          "subscribed_channels": {
            "description": "Channels to subscribe this rule to, each with an optional severity floor. Replaces the existing set (pass an empty array to clear all).",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RuleChannelLinkDto"
            }
          }
        },
        "required": [
          "subscribed_channels"
        ]
      },
      "DeleteAlertRuleResponseDto": {
        "type": "object",
        "properties": {
          "acknowledged": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "acknowledged"
        ]
      }
    }
  },
  "security": [
    {
      "Authorization": []
    }
  ]
}