API reference · v1 · updated 28 Sep 2026

Feyn API

Everything the website shows, as JSON: the verdict, every scam (S) and malicious (M) finding, and the wallets and transactions behind each one. Request a report over HTTPS, or subscribe over a WebSocket and get it live.

Base URL
https://api.feyn.fun
Auth
API key (Authorization: Bearer) or an x402 payment
Format
JSON, schema feyn.report/1
Live
wss://api.feyn.fun/v1/ws, free

Payments open at the $FEYN launch.

Until then /v1/token/{mint} and its summary are free, within the per-IP rate limits, and need no key or payment. The endpoints marked Available at launch answer 404 until then. Everything below is the API as it runs from the launch.

Getting started

Quickstart

  1. Get a key. Buy a credit pack on the pricing page with one payment from your Solana wallet. The starter pack is $5 for 1,000 credits. The key is shown once; keep it in an environment variable.
  2. Ask for a token. One report costs 1 credit. Every response says how many are left in X-Feyn-Credits-Remaining.
  3. Read the verdict. token.verdict.level is scam (an S-class finding fired), high_risk or caution (M-class findings only), clean (nothing fired: no flags, which is not a promise) or insufficient_data.
curl https://api.feyn.fun/v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump \
  -H "Authorization: Bearer $FEYN_API_KEY"

Until the $FEYN launch, leave the key out: the same request is free, within the per-IP rate limits. From the launch it answers 402 without one.

Authentication

Send your API key as a bearer token. Keys start with feyn_sk_. Feyn stores only a hash of each key, so keep yours out of client-side code and logs.

API key header
GET /v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump HTTP/1.1
Host: api.feyn.fun
Authorization: Bearer feyn_sk_…

Every keyed response carries two headers:

HeaderMeaning
X-Feyn-Credits-RemainingCredits left on the key after this call.
X-Feyn-Key-ExpiresWhen the key expires, in unix seconds.
X-Request-IdOn every response, keyed or not. Quote it when something goes wrong.

What is free: a bad address (400) or an unknown token (404) is answered before any charge. A 304 revalidation is refunded. If the server fails after charging (5xx), the credits come back.

The website, the Telegram bot, the WebSocket, /v1/resolve, /v1/blob and /healthz need no key.

Paying with x402

Available at launch Payments open at the $FEYN launch.

Payments use x402 v2 with the Solana exact scheme: a 402 answer carries a quote, you pay it with one token transfer, and repeat the request with the payment attached. Feyn runs its own facilitator and pays the network fee. Pay in USDC at list price, or in $FEYN at 15% off. SOL is not accepted.

Single call

Without a key, GET /v1/token/{mint} costs $0.01 per report, paid on the request itself. Paid attempts are limited to 2 per second per IP.

  1. Client to Feyn API: GET /v1/token/{mint}, no key
  2. Feyn API to Client: 402 with PAYMENT-REQUIRED: one quote per asset, each with extra.memo
  3. Client: Build the transfer, sign as payer only
  4. Client to Feyn API: Same request + PAYMENT-SIGNATURE
  5. Feyn API to Solana: Co-sign as fee payer, simulate, broadcast
  6. Solana to Feyn API: Confirmed
  7. Feyn API to Client: 200 with the report + PAYMENT-RESPONSE

The transaction must have exactly this shape, or it is refused before broadcast:

#InstructionRule
0ComputeBudget SetComputeUnitLimitNo accounts, at most 100,000 units.
1ComputeBudget SetComputeUnitPriceNo accounts, at most 50,000 micro-lamports per unit.
2TransferChecked (SPL Token or Token-2022)The exact amount of the quoted asset to the associated token account of payTo, signed by the payer.
3MemoExactly extra.memo: the quote, signed by the server.

Two signers only (the fee payer extra.feePayer at index 0, then you), no address lookup tables, no extra instructions. Wallets that inject Lighthouse assertions are refused.

402 Payment Required (body; the header holds the same JSON, base64)
{
  "x402Version": 2,
  "error": "payment required",
  "resource": {
    "url": "https://api.feyn.fun/v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump",
    "description": "Feyn token report",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
      "amount": "10000",
      "asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "payTo": "<vault owner>",
      "maxTimeoutSeconds": 300,
      "extra": {
        "feePayer": "<facilitator>",
        "memo": "feyn1:c:usdc:10000:<exp>:<nonce>:<mac>",
        "name": "USDC",
        "decimals": 6
      }
    },
    {
      "…": "the same for $FEYN at 15% off (maxTimeoutSeconds ≤ 60), while a TWAP quote exists"
    }
  ]
}
# 1. The quote
curl -si https://api.feyn.fun/v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump | grep -i payment-required

# 2. Sign the transfer with an x402 v2 client, then:
curl https://api.feyn.fun/v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump \
  -H "PAYMENT-SIGNATURE: $PAYMENT_B64"

Credit packs

A pack is bought the same way, from POST /v1/keys?pack=…: the paid request answers 201 with the key. A payment buys exactly one key; a replayed payment is refused. The key becomes active once its payment is final (usually within seconds; otherwise the answer is 202 and the key activates on first use).

  1. Client to Feyn API: POST /v1/keys?pack=starter
  2. Feyn API to Client: 402 with the pack's quotes
  3. Client: Build the transfer, sign as payer only
  4. Client to Feyn API: Same request + PAYMENT-SIGNATURE
  5. Feyn API to Solana: Co-sign, broadcast, wait until final
  6. Feyn API to Client: 201 with the key, shown once
  7. Client to Feyn API: Every later call: Authorization: Bearer feyn_sk_…

USDC quotes hold for 300 seconds and $FEYN quotes for 60. The $FEYN price is a 10-minute average of its own trades; no $FEYN quote is offered while that price is unreliable, and USDC is always offered. On the website, the pricing page does all of this with your wallet.

Credits and pricing

Every call with a key spends credits. Prices and costs below come from the same configuration the API server loads. $FEYN prices are 15% below the USDC price.

CallCredits
GET /v1/token/{mint}, the full report1
GET /v1/token/{mint}/summary1
Evidence or wallet-graph export2
Batch lookup, per token1
/v1/keys/self, /v1/pricing, /v1/resolve, /v1/blob, /healthz0
PackUSDCIn $FEYNCreditsKey lifetime
Starter$5$4.251,00030 days
Builder$25$21.256,00030 days
Pro$100$8530,00060 days
Enterprise$500$425200,00090 days
Single call (x402, no key)$0.01$0.00851 report—

A key's lifetime counts from its payment. Credits left at expiry expire with it. Every pack gets the same data.

Rate limits

Each key has its own limit, set by its pack. Over it, the answer is 429 rate_limited with Retry-After (seconds) and retry_after_s in the body.

WhoRequests/sBurst
Starter key510
Builder key1020
Pro key2040
Enterprise key200400
x402 paid attempts, per IP24
Free lookups (no key, paid mode off), per IP30/min15

Payments have two more limits that protect the fee payer. A network (IPv4 /24, IPv6 /48) whose payments failed on chain and used its share of the fee budget gets 429 network_throttled for 5 minutes. Under a drain attempt new payers settle one at a time, and a payment that waits over 10 s gets 503 settlement_busy. API keys are never affected by either.

Errors

Every error has the same JSON body. Switch on code, never on msg. retry_after_s (and the Retry-After header) appear when waiting helps.

Error body
{
  "error": {
    "code": "key_expired",
    "msg": "key expired",
    "request_id": "01J9…",
    "retry_after_s": 5
  }
}
HTTP error codes
StatusCodeWhenWhat to do
400bad_requestA bad query parameter, blob hash or resolve query.Fix the request. Nothing was charged.
400invalid_addressThe path address is not base58 or not 32 bytes (64 bytes is a signature).Fix the address. Nothing was charged.
400invalid_paymentPAYMENT-SIGNATURE is not base64 JSON of a PaymentPayload.Fix the encoding. Nothing was charged.
401invalid_keyThe key is malformed, unknown or revoked, or its payment failed or never landed.Check the Authorization header, or buy a new pack.
401key_pendingThe key's payment is not final yet.Retry after Retry-After seconds.
401key_expiredThe key is past expires_at.Buy a new pack. Unused credits expire with the key.
401invalid_signatureKey recovery: the message was not signed by the wallet that paid.Sign with the paying wallet.
402credits_exhaustedThe key has no credits left.Buy a new pack.
403payer_blockedThis payer, source account or IP had 3 payments fail on chain within 24 h.Wait 24 h, or use an API key.
404not_a_mintThe address is a curve, pool, wallet or other account; the body's resolved names its mint.Follow resolved.mint. Nothing was charged.
404not_indexedA pump.fun token created before Feyn started indexing, with no activity since (no backfill).Nothing to fetch until it trades again. Nothing was charged.
404not_foundUnknown resource, or the token is not one Feyn tracks.Check the path. Nothing was charged.
404unknown_refA blob hash that is not stored.Re-read the report for current refs. Nothing was charged.
405method_not_allowedA method the endpoint does not take (GET, HEAD and OPTIONS everywhere; POST only on /v1/keys).Use the documented method.
409payment_in_flightAnother payment from this payer or source account is not settled yet.Retry after Retry-After (5 s).
409already_usedKey recovery: this signed message was already used.Sign a new message with a fresh timestamp.
429rate_limitedOver the key's tier, the per-IP paid-attempt limit or the free lookup budget.Back off for Retry-After seconds.
429network_throttledPayments from your client network (IPv4 /24, IPv6 /48) failed on chain and used its share of the fee budget.Retry after Retry-After (300 s), or use an API key.
500internalAn unexpected failure. Credits taken for the call are refunded.Retry once, then report the X-Request-Id.
503settlement_pendingA single-call payment was broadcast but has not confirmed in time.Check PAYMENT-RESPONSE.transaction, then re-send the same PAYMENT-SIGNATURE rather than paying again.
503settlement_pausedThe fee-payer spend budget for your payer class (or overall) is used up.Pay later (Retry-After, 60 s) or use an API key.
503settlement_busyNew payers settle one at a time during a drain attempt, and your turn did not come within 10 s.Retry shortly (Retry-After, 2 s).
503unavailableOverload, warm-up, a standby server, or the key store, payment store or RPC is down.Retry after Retry-After seconds.

A refused payment answers 402 with fresh quotes and a PAYMENT-RESPONSE whose errorReason says why:

invalid_payment_requirements
The quote is unknown, altered or expired. Ask for a fresh 402 and pay again.
duplicate_settlement
This payment was already used. One payment buys exactly one key or call.
insufficient_funds
The paying wallet does not hold enough of the asset.
invalid_transaction_state
The payment transaction failed on chain.
invalid_exact_svm_payload_transaction_*
The transaction is not exactly the accepted shape (compute budget, one TransferChecked, the memo).

Reference

Tokens

GET/v1/token/{mint}

The full report (feyn.report/1) for an indexed pump.fun token: the verdict, every finding with its evidence tables and graphs, holders and context. 1 credit, or $0.01 with x402.

Parameters

NameInTypeDescription
mintrequiredpathbase58The token's mint address (32 bytes). Case-sensitive.
sectionsquerylistComma list of summary, scam, malicious, context, tables, graphs. Default: all. Fields not selected are left out; schema, mint, rev, slot, updated_at, coverage, addrs, labels, hashes are always there.
inlinequerylistComma list of sigs, graphs, tables: include those lazy chunks in a top-level chunks map keyed by ref (up to 8 MB; chunks_truncated when capped). Otherwise fetch them from /v1/blob.
AuthorizationheaderstringBearer API key. Or send PAYMENT-SIGNATURE instead.
If-None-MatchheaderetagThe ETag you hold (the report's rev). A match answers 304, not charged.

Responses

200
The report. ETag and X-Feyn-Rev hold its revision.
304
Unchanged since If-None-Match.
400
invalid_address or bad_request. Free.
402
Payment required (x402 quotes), or credits_exhausted.
404
not_a_mint (the body's resolved names the token), not_indexed or not_found. Free.
429
rate_limited or network_throttled.
503
unavailable, or a payment state: settlement_pending, settlement_paused, settlement_busy.
curl https://api.feyn.fun/v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump?sections=summary,malicious \
  -H "Authorization: Bearer $FEYN_API_KEY"
200 · sections=summary,malicious
{
  "schema": "feyn.report/1",
  "mint": "B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump",
  "rev": 450641306003,
  "slot": 450641306,
  "updated_at": 1790416804,
  "coverage": {
    "indexed_since_slot": 450300000,
    "complete": true
  },
  "addrs": [
    "D9gQ6RhKEpnobPBUdWY5bPQt2p3zGk3iVz6ChpUi2ArA",
    "tExRzb1XFwHP9A5jnZyJTfDTpFtRvNSn3FhGoVY1GuB"
  ],
  "labels": [
    {
      "a": 0,
      "kind": "creator"
    },
    {
      "a": 1,
      "kind": "curve"
    }
  ],
  "token": {
    "name": "Example Small Curve",
    "symbol": "SMOL",
    "creator": 0,
    "created_slot": 450636806,
    "created_at": 1790415600,
    "venue": "curve",
    "quote_mint": "So11111111111111111111111111111111111111112",
    "curve": {
      "address": 1,
      "progress_bps": 1661,
      "real_quote_reserves": 4200000000,
      "complete": false,
      "mayhem_mode": false
    },
    "price_quote": 3.6335507921714823e-8,
    "price_usd": 0.00000545,
    "mcap_usd": 5450,
    "liquidity_usd": 630,
    "supply_raw": 1000000000000000,
    "decimals": 6,
    "holders": {
      "total": 14,
      "fake_dust": 0,
      "top10_bps": 1873,
      "top10_true_bps": 1873
    },
    "launch_block_bps": 346,
    "trades_24h": {
      "buys": 21,
      "sells": 7,
      "volume_quote": 5900000000,
      "organic_volume_bps": 10000
    },
    "traders": {
      "total": 16,
      "fresh_bps": 0,
      "flagged_bps": 0
    },
    "verdict": {
      "scam": false,
      "level": "caution",
      "scam_ids": [],
      "malicious_ids": [
        "M004"
      ],
      "headline": "No scam detected. Malicious behaviour found: Block-0 buyers."
    }
  },
  "malicious_behaviour": [
    {
      "name": "Block-0 buyers",
      "headline": "3.46% of the supply was bought in the same block the token launched, by the creator alone.",
      "explanation": "The creator bought in the same block the token was created, before anyone else could see it. The creator spent 1 SOL. The creator still holds all of it. The table shows exactly who bought, how much and in what order.\n\nWhy it matters: A creator's launch-block buy is visible to everyone and is common; it matters if the creator sells into later buyers.",
      "severity": 2,
      "confidence": "standard",
      "first_detected_slot": 450636806,
      "updated_slot": 450636806,
      "wallets": [
        0
      ],
      "examples": [],
      "tables": [
        "block0_buyers"
      ],
      "id": "M004",
      "metrics": {
        "create_slot": 450636806,
        "create_ix": 212,
        "buyers": 1,
        "supply_bps": 346,
        "tokens_raw": 34612903225806,
        "quote_spent": 1000000000,
        "tips_lamports": 0,
        "creator_included": true,
        "creator_supply_bps": 346,
        "largest_non_creator_bps": 0,
        "linked_to_creator": 0,
        "held_now_bps": 346,
        "true_held_bps": 346
      }
    }
  ],
  "hashes": {
    "addrs": "9bc01ae70874bc54",
    "malicious/M004": "d9b2b17dca920c51",
    "summary": "0a9aa2fe03249a92"
  }
}
A real report: the schema fixture “small curve”, one M-class finding (M004).

GET/v1/token/{mint}/summary

The verdict, the headline of each finding and the key figures: exactly the WebSocket's summary frame. Small and fast; the Telegram bot renders from it. 1 credit.

Parameters

NameInTypeDescription
mintrequiredpathbase58The token's mint address.

Same statuses, ETag and payment rules as the full report. No query parameters.

curl https://api.feyn.fun/v1/token/B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump/summary \
  -H "Authorization: Bearer $FEYN_API_KEY"
200 · Summary
{
  "schema": "feyn.report/1",
  "mint": "B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump",
  "rev": 450641306003,
  "slot": 450641306,
  "updated_at": 1790416804,
  "coverage": {
    "indexed_since_slot": 450300000,
    "complete": true
  },
  "addrs": [
    "D9gQ6RhKEpnobPBUdWY5bPQt2p3zGk3iVz6ChpUi2ArA",
    "tExRzb1XFwHP9A5jnZyJTfDTpFtRvNSn3FhGoVY1GuB"
  ],
  "token": {
    "name": "Example Small Curve",
    "symbol": "SMOL",
    "creator": 0,
    "created_slot": 450636806,
    "created_at": 1790415600,
    "venue": "curve",
    "quote_mint": "So11111111111111111111111111111111111111112",
    "curve": {
      "address": 1,
      "progress_bps": 1661,
      "real_quote_reserves": 4200000000,
      "complete": false,
      "mayhem_mode": false
    },
    "price_quote": 3.6335507921714823e-8,
    "price_usd": 0.00000545,
    "mcap_usd": 5450,
    "liquidity_usd": 630,
    "supply_raw": 1000000000000000,
    "decimals": 6,
    "holders": {
      "total": 14,
      "fake_dust": 0,
      "top10_bps": 1873,
      "top10_true_bps": 1873
    },
    "launch_block_bps": 346,
    "trades_24h": {
      "buys": 21,
      "sells": 7,
      "volume_quote": 5900000000,
      "organic_volume_bps": 10000
    },
    "traders": {
      "total": 16,
      "fresh_bps": 0,
      "flagged_bps": 0
    },
    "verdict": {
      "scam": false,
      "level": "caution",
      "scam_ids": [],
      "malicious_ids": [
        "M004"
      ],
      "headline": "No scam detected. Malicious behaviour found: Block-0 buyers."
    }
  },
  "findings": [
    {
      "id": "M004",
      "name": "Block-0 buyers",
      "headline": "3.46% of the supply was bought in the same block the token launched, by the creator alone.",
      "severity": 2
    }
  ]
}

GET/v1/resolve/{q}

What an address or link is: a mint, its bonding curve or pool, a creator wallet, or not a token. Use it to turn a curve, pool or pump.fun link into the mint to ask for. Free.

Parameters

NameInTypeDescription
qrequiredpathstringAn address, or a percent-encoded pump.fun/coin/…, solscan.io/token/… or dexscreener.com/solana/… link. Up to 256 characters.

kind is one of mint, curve, pool, creator (with up to 20 tokens), wallet, unknown_token, not_a_token, invalid (with a reason) or not_indexed. Every well-formed request answers 200; the answer is the kind, not the status.

curl https://api.feyn.fun/v1/resolve/tExRzb1XFwHP9A5jnZyJTfDTpFtRvNSn3FhGoVY1GuB
200 · resolved
{
  "q": "tExRzb1XFwHP9A5jnZyJTfDTpFtRvNSn3FhGoVY1GuB",
  "kind": "curve",
  "mint": "B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump",
  "name": "Example Small Curve",
  "symbol": "SMOL"
}

GET/v1/blob/{hash}

A lazy chunk of a report: a page of signatures, a table page or a subgraph, by the ref a report points at. Immutable and cached for a year. Free.

Parameters

NameInTypeDescription
hashrequiredpathhex(16)A Ref.ref from the report (Finding.txs, Table.next, GraphManifest.expand, …).

X-Feyn-Chunk says what it is: sigs, table or graph. A ref is kept for at least 24 hours after the last report that uses it.

curl https://api.feyn.fun/v1/blob/d550411a3d83bf4a

Reference

Keys and payments

POST/v1/keys?pack={name}Available at launch

Buy a credit pack. Without payment the answer is a 402 quote for the pack; with PAYMENT-SIGNATURE it is the key.

Parameters

NameInTypeDescription
packrequiredquerystringstarter, builder, pro, enterprise.
PAYMENT-SIGNATUREheaderbase64base64 JSON of the x402 PaymentPayload for one of the quotes.

Responses

201
The key, shown once. Feyn stores only its SHA-256.
202
status: "pending": the payment was broadcast but is not final yet; the key activates on first use once it is.
402
The quote (starter: 5000000 USDC atoms), or a refused payment with errorReason.
403 · 409 · 429 · 503
payer_blocked, payment_in_flight, network_throttled, settlement_paused / settlement_busy.
# The quote for the starter pack
curl -si -X POST "https://api.feyn.fun/v1/keys?pack=starter"

# Paid (see Paying with x402)
curl -X POST "https://api.feyn.fun/v1/keys?pack=starter" \
  -H "PAYMENT-SIGNATURE: $PAYMENT_B64"
201 · key issued
{
  "key": "feyn_sk_…",
  "status": "active",
  "pack": "starter",
  "credits": 1000,
  "rate_limit": {
    "per_s": 5,
    "burst": 10
  },
  "lifetime_days": 30,
  "expires_at": 1793008800,
  "transaction": "<signature>"
}

POST/v1/keys/recoverAvailable at launch

Lost the key? The wallet that paid for it signs a message and gets a new secret for the same key (same credits and expiry). The old secret stops working.

Parameters

NameInTypeDescription
transactionrequiredbodybase58The signature of the transaction that paid for the key.
timestamprequiredbodyunix sNow; must be within 5 minutes of the server's clock.
signaturerequiredbodybase58The paying wallet's signMessage over feyn-key-recovery:v1:<network>:<transaction>:<timestamp> (UTF-8).

Responses

201
A new secret for the same key.
401
invalid_signature: signed by another wallet.
404
The transaction paid for a single call, or failed.
409
already_used: each signed message works once.
curl -X POST https://api.feyn.fun/v1/keys/recover \
  -H "Content-Type: application/json" \
  -d '{"transaction":"<base58>","timestamp":1790416804,"signature":"<base58>"}'

GET/v1/keys/selfAvailable at launch

Your key's credits, expiry, tier and paying transaction. Costs no credits (it does count against the tier's rate limit). The key page uses it.

Parameters

NameInTypeDescription
AuthorizationrequiredheaderstringBearer API key.

expires_at is null while the payment is not final (the lifetime starts from the payment). status is active or pending.

curl https://api.feyn.fun/v1/keys/self \
  -H "Authorization: Bearer $FEYN_API_KEY"
200 · key
{
  "pack": "starter",
  "status": "active",
  "credits_total": 1000,
  "credits_left": 830,
  "expires_at": 1793008800,
  "rate_limit": {
    "per_s": 5,
    "burst": 10
  },
  "transaction": "<signature>"
}

GET/v1/pricingAvailable at launch

Packs, credit costs, payment assets and the current $FEYN rate. Free; cached for 10 seconds.

No parameters.

curl https://api.feyn.fun/v1/pricing
200 · pricing
{
  "x402Version": 2,
  "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
  "fee_payer": "<facilitator>",
  "single_call": {
    "price_usdc": "0.01",
    "price_feyn_atoms": "85000000",
    "rate_limit_per_ip": {
      "per_s": 2,
      "burst": 4
    }
  },
  "credit_costs": {
    "report": 1,
    "summary": 1,
    "export": 2,
    "batch_per_token": 1
  },
  "packs": [
    {
      "name": "starter",
      "price_usdc": "5",
      "price_feyn_atoms": "42500000000",
      "credits": 1000,
      "lifetime_days": 30,
      "rate_limit": {
        "per_s": 5,
        "burst": 10
      }
    },
    {
      "name": "builder",
      "price_usdc": "25",
      "price_feyn_atoms": "212500000000",
      "credits": 6000,
      "lifetime_days": 30,
      "rate_limit": {
        "per_s": 10,
        "burst": 20
      }
    },
    {
      "name": "pro",
      "price_usdc": "100",
      "price_feyn_atoms": "850000000000",
      "credits": 30000,
      "lifetime_days": 60,
      "rate_limit": {
        "per_s": 20,
        "burst": 40
      }
    },
    {
      "name": "enterprise",
      "price_usdc": "500",
      "price_feyn_atoms": "4250000000000",
      "credits": 200000,
      "lifetime_days": 90,
      "rate_limit": {
        "per_s": 200,
        "burst": 400
      }
    }
  ],
  "assets": {
    "usdc": {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "decimals": 6
    },
    "feyn": {
      "mint": "<$FEYN mint>",
      "decimals": 6,
      "discount_bps": 1500,
      "usdc_per_feyn_twap": 0.0001,
      "quote_ttl_s": 60
    }
  }
}
From the live configuration, at an example rate of 0.0001 USDC per $FEYN. price_feyn_atoms is null while $FEYN has no quote.

GET/v1/x402/supportedAvailable at launch

The facilitator's supported schemes and networks (x402 v2 SupportedResponse), for x402 clients that check before paying. Free.

Lists the exact scheme on solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp with the fee payer in extra.feePayer.

curl https://api.feyn.fun/v1/x402/supported

GET/healthz

Liveness and ingest lag, for uptime checks. Not versioned, not rate-limited, never cached.

Responses

200
"ok": serving, ingest lag within target. "degraded": serving, but reports are behind.
503
"starting" or "down": not ready.
curl https://api.feyn.fun/healthz
200 · health
{
  "status": "ok",
  "slot": 450641306,
  "lag_s": 1.2
}

Reference

WebSocket

WSwss://api.feyn.fun/v1/ws

The live feed the website uses: subscribe to a token and get its summary, then each section, then patches as trades land. Free, no auth, rate-limited per IP. The protocol is feyn.ws/1.

Send hello first, then one sub per token (up to 4 per socket; ids strictly increasing). Binary frames carry the data, text frames the control messages. Receivers must ignore unknown fields, message types and section keys: additive changes do not bump the version.

# websocat (github.com/vi/websocat); text frames only
websocat wss://api.feyn.fun/v1/ws
{"type":"hello","v":1,"codecs":[]}
{"type":"sub","id":1,"q":"B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump"}

Messages

DirectiontypeWhat it does
client to serverhelloMust be first: {v: 1, codecs: ["deflate-raw"]}. You may send sub right after without waiting.
client to serversubSubscribe: id, q (a mint, curve, pool or link), optional rev to resume and want to pick sections.
client to serverunsubStop a sub by id. Frames already in flight are dropped by you.
client to servergetA lazy chunk by ref; the answer is one binary chunk frame.
client to serverpingEvery 30 s while visible, with t; no reply within 15 s means the socket is dead.
server to clienthello_ackServer time, max_subs, the codecs it will use, ping_interval_s.
server to clientresolvedFirst reply to every sub: what q is. Only mint, curve and pool go on to stream.
server to clientdoneThe first view (or resume) is complete at rev, with the hash of every section.
server to clientpongEchoes t.
server to clienterrorA code (below), with the sub's id when it concerns one.
First view of a token, frame by frame
→ {"type":"hello","v":1,"codecs":["deflate-raw"]}
→ {"type":"sub","id":1,"q":"B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump"}
← {"type":"hello_ack","v":1,"server_time":1790416804123,"max_subs":4,"codecs":["deflate-raw"],"ping_interval_s":30}
← {"type":"resolved","id":1,"q":"B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump","kind":"mint","mint":"B4HpTokrHXwYGQUYCN1axBH54pYf483Bpw5sCft2pump","name":"Example Small Curve","symbol":"SMOL"}
← [01 01 01 00 00 00] summary summary · deflate-raw · 763 B
← [00 02 01 00 00 00] section addrs · identity · 227 B
← [01 02 01 00 00 00] section malicious/M004 · deflate-raw · 541 B
← [00 02 01 00 00 00] section context · identity · 348 B
← [01 02 01 00 00 00] section tables/block0_buyers · deflate-raw · 422 B
← [01 02 01 00 00 00] section tables/holders · deflate-raw · 414 B
← {"type":"done","id":1,"rev":450641306003,"mode":"snapshot","hashes":{"addrs":"9bc01ae70874bc54","context":"ff7ccdae6732ed75","malicious/M004":"d9b2b17dca920c51","summary":"0a9aa2fe03249a92","tables/block0_buyers":"15880e004c033b06","tables/holders":"0fab2cce775fb660"}}
A real transcript: the fixture token's first view (docs/api/examples). Binary frames are shown as header bytes, kind, key, codec and size.

Binary frames

Every binary frame starts with a 6-byte header, then the payload: JSON, deflated with raw DEFLATE when it is 512 bytes or more and you listed the codec.

OffsetSizeFieldValues
01codec0 = identity (UTF-8 JSON), 1 = deflate-raw
11kind1 = summary, 2 = section, 3 = patch, 4 = chunk
24subu32 little-endian: the subscription id
6npayloadencoded per codec

Process frames in arrival order (decompression is asynchronous). Drop frames with an unknown codec or kind, and frames for subs you no longer hold.

Limits and errors

Per socket: 4 subs, 10 sub/s, 20 get/s, 50 messages/s, frames up to 2,048 bytes. Per IP: 60 new sockets a minute, 30 lookups a minute (burst 15; a token you looked up in the last 10 minutes is free), 32 live subs. After 20 refused lookups in 10 minutes an IP is challenged (Turnstile). Reconnect with backoff 0.25 → 0.5 → 1 → 2 → 4 → 8 s, then resume each sub with its rev.

WebSocket error codes
error.codeMeaningWhat to do
bad_requestMalformed JSON, an unknown type, a missing field or a sub id that did not increase. The socket stays open.Fix the client; don't retry blindly.
rate_limitedA sub or get was refused; retry_after_ms says when. msg "verification required" means the IP is challenged.Retry after the delay; if challenged, solve Turnstile and reconnect with ?turnstile=.
too_many_subsThe sub with this id was ended to make room (4 per socket).Stop rendering it.
unknown_refA get for a ref the server does not have.Fall back to GET /v1/blob/{ref} once.
overloadedThe server is shedding load; the sub did not start.Back off and retry the sub.
internalAn unexpected failure; the sub (if any) ended.Retry the sub once after 1 s.
hello_requiredThe first frame was not hello (sent just before close 4001).Send hello first.
unsupported_versionhello.v is not supported (sent just before close 4002).Don't reconnect; update the client.
WebSocket close codes
CloseMeaningReconnect
1000Normal close (tab hidden over 5 min, navigation).On demand
1001Going away: restart or deploy.Yes, back off from step 0
1003The client sent a binary frame.No (client bug)
1006Abnormal drop (network, Cloudflare restart).Yes, back off
1008Policy: inbound message flood.Yes, start at 8 s
1009Inbound frame over 2,048 bytes.Yes, back off
1011Internal error.Yes, back off
4001First frame was not hello.Yes, after fixing the order
4002hello.v unsupported.No: reload the page
4008Slow consumer.Yes, back off
4029Too many sockets from this IP.Yes, start at 8 s

More

Changelog

  1. 28 Sep 2026

    API v1, first public version. Reports (feyn.report/1), the WebSocket (feyn.ws/1), API keys and x402 payments in USDC or in $FEYN at 15% off.

  2. Versioning

    The path carries the major version (/v1). New optional fields, message types, section keys and error codes are added without a new version, so ignore what you don't know. A breaking change moves to /v2.