{
 "openapi": "3.1.0",
 "info": {
  "title": "Farbeam API",
  "version": "1.0.0",
  "description": "On-chain data API. Data only, not financial advice."
 },
 "servers": [
  {
   "url": "https://farbeamlabs.com/api/v1"
  }
 ],
 "components": {
  "securitySchemes": {
   "bearer": {
    "type": "http",
    "scheme": "bearer"
   }
  }
 },
 "paths": {
  "/health": {
   "get": {
    "operationId": "health",
    "summary": "Service health",
    "description": "Returns a small health summary. It does not count against your rate limit.",
    "tags": [
     "Service"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/status": {
   "get": {
    "operationId": "status",
    "summary": "Status",
    "description": "Returns the live state of each chain poller and each outbound data source, measured by this service.",
    "tags": [
     "Service"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/status/history": {
   "get": {
    "operationId": "status-history",
    "summary": "Status history",
    "description": "Returns stored health samples per chain, one every 5 minutes, kept for 30 days.",
    "tags": [
     "Service"
    ],
    "parameters": [
     {
      "name": "hours",
      "in": "query",
      "required": false,
      "description": "Hours to return, from 1 to 720. Default 24.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/chains": {
   "get": {
    "operationId": "chains",
    "summary": "List chains",
    "description": "Returns coverage and current state for every chain.",
    "tags": [
     "Chains"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/chains/{chain}": {
   "get": {
    "operationId": "chain",
    "summary": "Get a chain",
    "description": "Returns coverage and current state for one chain.",
    "tags": [
     "Chains"
    ],
    "parameters": [
     {
      "name": "chain",
      "in": "path",
      "required": true,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The chain is unknown."
     }
    }
   }
  },
  "/chains/{chain}/blocks": {
   "get": {
    "operationId": "blocks",
    "summary": "Recent blocks",
    "description": "Returns the most recent blocks this service read. The list holds at most 25 blocks and is kept in memory. On Solana each entry is a sampled slot.",
    "tags": [
     "Chains"
    ],
    "parameters": [
     {
      "name": "chain",
      "in": "path",
      "required": true,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "From 1 to 25. Default 10.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "A parameter is out of range."
     }
    }
   }
  },
  "/gas": {
   "get": {
    "operationId": "gas",
    "summary": "Gas and fees",
    "description": "Returns current fee data for every chain, with the native asset price in USD.",
    "tags": [
     "Chains"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/prices": {
   "get": {
    "operationId": "prices",
    "summary": "Asset prices",
    "description": "Returns the USD prices this service uses to value transfers. Source: CoinGecko, refreshed about once a minute.",
    "tags": [
     "Chains"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/transfers": {
   "get": {
    "operationId": "transfers",
    "summary": "List large transfers",
    "description": "Returns stored transfers of at least $100,000, newest first, with labels where known.",
    "tags": [
     "Transfers"
    ],
    "parameters": [
     {
      "name": "chain",
      "in": "query",
      "required": false,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "token",
      "in": "query",
      "required": false,
      "description": "Token symbol, such as USDC. Not case sensitive.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "min_usd",
      "in": "query",
      "required": false,
      "description": "Lowest USD value to return.",
      "schema": {
       "type": "number"
      }
     },
     {
      "name": "address",
      "in": "query",
      "required": false,
      "description": "Return transfers where this address is the sender or the recipient.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "before",
      "in": "query",
      "required": false,
      "description": "Cursor. Pass meta.next_cursor from the last page.",
      "schema": {
       "type": "integer"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "From 1 to 100. Default 25.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "A parameter is out of range."
     }
    }
   }
  },
  "/transfers/stats": {
   "get": {
    "operationId": "transfer-stats",
    "summary": "Transfer statistics",
    "description": "Returns count and USD totals of stored transfers by chain and by token.",
    "tags": [
     "Transfers"
    ],
    "parameters": [
     {
      "name": "hours",
      "in": "query",
      "required": false,
      "description": "Window, from 1 to 168. Default 24.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "A parameter is out of range."
     }
    }
   }
  },
  "/wallets/{address}": {
   "get": {
    "operationId": "wallet",
    "summary": "Wallet overview",
    "description": "Returns native and curated-token balances. An EVM address is read on all six EVM chains. A Solana address also returns recent signatures.",
    "tags": [
     "Wallets"
    ],
    "parameters": [
     {
      "name": "address",
      "in": "path",
      "required": true,
      "description": "EVM or Solana address.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The address format does not match the chain."
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/wallets/{address}/activity": {
   "get": {
    "operationId": "wallet-activity",
    "summary": "Wallet activity",
    "description": "Returns recent curated-token transfers on one EVM chain, or recent signatures on Solana.",
    "tags": [
     "Wallets"
    ],
    "parameters": [
     {
      "name": "address",
      "in": "path",
      "required": true,
      "description": "EVM or Solana address.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "chain",
      "in": "query",
      "required": false,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana. Default is ethereum for EVM addresses and solana for Solana addresses.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The chain is unknown."
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/tokens/{chain}/{address}": {
   "get": {
    "operationId": "token",
    "summary": "Token report",
    "description": "Returns market data, contract and authority checks, top holders and largest pools.",
    "tags": [
     "Tokens"
    ],
    "parameters": [
     {
      "name": "chain",
      "in": "path",
      "required": true,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "address",
      "in": "path",
      "required": true,
      "description": "Token contract or mint address.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The address format does not match the chain."
     },
     "404": {
      "description": "The item does not exist."
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/tx/{chain}/{hash}": {
   "get": {
    "operationId": "tx",
    "summary": "Transaction lookup",
    "description": "Returns status, fee, parties and decoded token movements of one transaction.",
    "tags": [
     "Transactions"
    ],
    "parameters": [
     {
      "name": "chain",
      "in": "path",
      "required": true,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "hash",
      "in": "path",
      "required": true,
      "description": "0x hash on EVM chains, base58 signature on Solana.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The hash format does not match the chain."
     },
     "404": {
      "description": "The item does not exist."
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/labels": {
   "get": {
    "operationId": "labels",
    "summary": "List labels",
    "description": "Returns the curated label set. You can search it and filter it.",
    "tags": [
     "Labels"
    ],
    "parameters": [
     {
      "name": "q",
      "in": "query",
      "required": false,
      "description": "Text to find in the name or the address.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "type",
      "in": "query",
      "required": false,
      "description": "exchange, dex, bridge, lending, staking, token, issuer, launchpad or infrastructure.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "chain",
      "in": "query",
      "required": false,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The chain is unknown."
     }
    }
   }
  },
  "/labels/{address}": {
   "get": {
    "operationId": "label",
    "summary": "Get a label",
    "description": "Returns the label of one address, or 404 when it has none.",
    "tags": [
     "Labels"
    ],
    "parameters": [
     {
      "name": "address",
      "in": "path",
      "required": true,
      "description": "EVM or Solana address.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The address format does not match the chain."
     },
     "404": {
      "description": "The item does not exist."
     }
    }
   }
  },
  "/markets/chains": {
   "get": {
    "operationId": "markets-chains",
    "summary": "Chain TVL",
    "description": "Returns the top 40 chains by total value locked. Source: DefiLlama, cached for 10 minutes.",
    "tags": [
     "Markets"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/markets/stablecoins": {
   "get": {
    "operationId": "markets-stablecoins",
    "summary": "Stablecoin supply",
    "description": "Returns the top 25 USD stablecoins and the top 25 chains by stablecoin supply. Source: DefiLlama, cached for 10 minutes.",
    "tags": [
     "Markets"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/markets/dexs": {
   "get": {
    "operationId": "markets-dexs",
    "summary": "DEX volume",
    "description": "Returns 24 hour DEX volume in total and for the top 30 protocols. Source: DefiLlama, cached for 15 minutes.",
    "tags": [
     "Markets"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/markets/pools": {
   "get": {
    "operationId": "markets-pools",
    "summary": "Trending pools",
    "description": "Returns pools that GeckoTerminal ranks as trending on one chain, cached for 5 minutes. A rank here is not a signal or a recommendation.",
    "tags": [
     "Markets"
    ],
    "parameters": [
     {
      "name": "chain",
      "in": "query",
      "required": false,
      "description": "One of ethereum, base, bnb, arbitrum, optimism, polygon, solana. Default solana.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The chain is unknown."
     },
     "502": {
      "description": "A public data source did not answer."
     }
    }
   }
  },
  "/rules/validate": {
   "post": {
    "operationId": "rules-validate",
    "summary": "Validate a rule",
    "description": "Parses a Beamline expression and tests it against the last 2,000 stored transfers. No key is needed.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "422": {
      "description": "The expression did not parse. The message gives the position."
     },
     "400": {
      "description": "The body is not a JSON object."
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       },
       "example": {
        "expression": "usd >= 1m and token in [\"USDC\",\"USDT\"]"
       }
      }
     }
    }
   }
  },
  "/auth/challenge": {
   "post": {
    "operationId": "auth-challenge",
    "summary": "Start wallet sign-in",
    "description": "Returns a message for a Solana wallet to sign. The message expires in 5 minutes and works once. Signing sends no transaction and costs nothing.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "400": {
      "description": "The address format does not match the chain."
     },
     "429": {
      "description": "A limit was reached. See `Retry-After`."
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       },
       "example": {
        "address": "BASE58_WALLET_ADDRESS"
       }
      }
     }
    }
   }
  },
  "/auth/verify": {
   "post": {
    "operationId": "auth-verify",
    "summary": "Finish wallet sign-in",
    "description": "Checks the ed25519 signature. If it matches, the reply sets an HttpOnly session cookie that lasts seven days.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The signature does not match the wallet and message."
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       },
       "example": {
        "address": "BASE58_WALLET_ADDRESS",
        "nonce": "NONCE_FROM_CHALLENGE",
        "signature": "BASE64_OR_BASE58_SIGNATURE"
       }
      }
     }
    }
   }
  },
  "/auth/session": {
   "get": {
    "operationId": "auth-session",
    "summary": "Session state",
    "description": "Says whether this browser has a valid session.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/auth/logout": {
   "post": {
    "operationId": "auth-logout",
    "summary": "Sign out",
    "description": "Ends the session and clears the cookie.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     }
    }
   }
  },
  "/account": {
   "get": {
    "operationId": "account",
    "summary": "Account",
    "description": "Returns the wallet address, the plan, limits, keys and Telegram state. Needs a session.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "Sign in with a wallet first."
     }
    }
   }
  },
  "/keys": {
   "post": {
    "operationId": "keys-create",
    "summary": "Create an API key",
    "description": "Creates a key and returns it once. Needs a session. An account can hold 5 active keys.",
    "tags": [
     "Keys"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "Sign in with a wallet first."
     },
     "409": {
      "description": "The account holds 5 active keys."
     }
    },
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       },
       "example": {
        "label": "my-app"
       }
      }
     }
    }
   }
  },
  "/keys/{id}": {
   "delete": {
    "operationId": "keys-delete",
    "summary": "Revoke a key",
    "description": "Revokes one key of this account. Needs a session. Rules stay with the account.",
    "tags": [
     "Keys"
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Key id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "Sign in with a wallet first."
     },
     "404": {
      "description": "The item does not exist."
     }
    }
   }
  },
  "/account/telegram": {
   "post": {
    "operationId": "telegram-link",
    "summary": "Link Telegram",
    "description": "Returns a bot link that works for 15 minutes. Open it and press Start to link a private chat. Answers 503 until the bot is connected.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "Sign in with a wallet first."
     },
     "503": {
      "description": "Telegram delivery is not connected yet."
     }
    }
   },
   "delete": {
    "operationId": "telegram-unlink",
    "summary": "Unlink Telegram",
    "description": "Removes the linked chat.",
    "tags": [
     "Account"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "Sign in with a wallet first."
     }
    }
   }
  },
  "/me": {
   "get": {
    "operationId": "me",
    "summary": "Current key",
    "description": "Returns the key record, its limits and up to 30 days of daily usage.",
    "tags": [
     "Keys"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The key is unknown or revoked."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "delete": {
    "operationId": "me-delete",
    "summary": "Revoke the current key",
    "description": "Revokes the key and turns off all its rules. This cannot be undone.",
    "tags": [
     "Keys"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The key is unknown or revoked."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/rules": {
   "get": {
    "operationId": "rules-list",
    "summary": "List rules",
    "description": "Returns all alert rules of this account, or of this key if the key has no account.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The key is unknown or revoked."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "post": {
    "operationId": "rules-create",
    "summary": "Create a rule",
    "description": "Creates an alert rule and returns its signing secret once. An account can hold 10 rules. `cooldown_seconds` is how long the rule waits after it fires, from 60 to 86400, default 300. `format` is `json`, `discord` or `telegram`. A Telegram rule needs no `url`.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The request has no key."
     },
     "422": {
      "description": "The webhook URL is not a public HTTPS URL."
     },
     "409": {
      "description": "The key already holds 10 rules."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       },
       "example": {
        "name": "Large stablecoin moves",
        "expression": "usd >= 5m and token in [\"USDC\",\"USDT\"]",
        "url": "https://example.com/hooks/farbeam",
        "format": "json"
       }
      }
     }
    }
   }
  },
  "/rules/{id}": {
   "get": {
    "operationId": "rule-get",
    "summary": "Get a rule",
    "description": "Returns one rule of this key.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Rule id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The request has no key."
     },
     "404": {
      "description": "The item does not exist."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   },
   "patch": {
    "operationId": "rule-update",
    "summary": "Update a rule",
    "description": "Changes any of `name`, `expression`, `url`, `format`, `cooldown_seconds` and `enabled`. Setting `enabled` to true also clears the failure count.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Rule id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The request has no key."
     },
     "404": {
      "description": "The item does not exist."
     },
     "422": {
      "description": "The webhook URL is not a public HTTPS URL."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "type": "object"
       },
       "example": {
        "enabled": false
       }
      }
     }
    }
   },
   "delete": {
    "operationId": "rule-delete",
    "summary": "Delete a rule",
    "description": "Deletes the rule and its delivery log.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Rule id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The request has no key."
     },
     "404": {
      "description": "The item does not exist."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/rules/{id}/test": {
   "post": {
    "operationId": "rule-test",
    "summary": "Send a test delivery",
    "description": "Queues a signed test delivery to the rule URL. Limit: 10 per hour per rule.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Rule id.",
      "schema": {
       "type": "string"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The request has no key."
     },
     "404": {
      "description": "The item does not exist."
     },
     "429": {
      "description": "A limit was reached. See `Retry-After`."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   }
  },
  "/rules/{id}/deliveries": {
   "get": {
    "operationId": "rule-deliveries",
    "summary": "List deliveries",
    "description": "Returns the delivery log of one rule, newest first. Log rows are kept for 14 days.",
    "tags": [
     "Alert rules"
    ],
    "parameters": [
     {
      "name": "id",
      "in": "path",
      "required": true,
      "description": "Rule id.",
      "schema": {
       "type": "string"
      }
     },
     {
      "name": "limit",
      "in": "query",
      "required": false,
      "description": "From 1 to 100. Default 25.",
      "schema": {
       "type": "integer"
      }
     }
    ],
    "responses": {
     "200": {
      "description": "Success"
     },
     "401": {
      "description": "The request has no key."
     },
     "404": {
      "description": "The item does not exist."
     }
    },
    "security": [
     {
      "bearer": []
     }
    ]
   }
  }
 }
}