Earn Products

A rate is only half the story. The earn products endpoints expose the canonical graph of what is actually on offer: each product is one provider × asset × category, and each of its variants carries the terms — lockup, tier, minimum deposit, payout cadence, withdrawal notice, TVL, promo status — along with how we collected each field, how confident we are, and where the product can be used. Use it to answer "what are the real terms behind this rate?"

Access and plan gating

Authenticate with your key as a Bearer token (see Authentication). Unlike the rate-change feed, there is no history window here — the graph is a current-state read — so the only plan question is whether the endpoint answers.

PlanEndpoint access
Anonymous (no key)403 PLAN_UPGRADE_REQUIRED
Free403 PLAN_UPGRADE_REQUIRED
Starter403 PLAN_UPGRADE_REQUIRED
Growth403 PLAN_UPGRADE_REQUIRED
ProFull
EnterpriseFull

The product model

A product is the stable identity a rate hangs off. It survives provider delistings: a delisted product keeps its id and its history, it just moves to status: "delisted".

Properties

  • Name
    id
    Type
    integer
    Description

    Stable numeric identifier. Use it with /earn/products/:id.

  • Name
    provider
    Type
    string
    Description

    Provider slug, e.g. "nexo", "aave-v3".

  • Name
    symbol
    Type
    string
    Description

    Asset symbol, upper-case.

  • Name
    category
    Type
    string
    Description

    lending, borrowing, or staking.

  • Name
    coinId
    Type
    string | null
    Description

    Canonical coin identifier, when the symbol resolved.

  • Name
    platformType
    Type
    string | null
    Description

    cefi, defi, or hybrid, from the provider registry.

  • Name
    status
    Type
    string
    Description

    active, inactive, or delisted.

  • Name
    firstObservedAt
    Type
    string
    Description

    ISO 8601 instant the product was first seen.

  • Name
    lastObservedAt
    Type
    string
    Description

    ISO 8601 instant the product was last seen in a provider's offer set.

  • Name
    variants
    Type
    array
    Description

    The product's variants (below). Present unless includeVariants=false. On the list endpoint only active variants are returned; the single-product endpoint returns variants of every status.


The variant model

A variant is one concrete offer of a product: the "flexible" tier and the "90-day locked" tier of the same asset are two variants. Any term we could not verify is null — we never guess.

Properties

  • Name
    id
    Type
    integer
    Description

    Variant identifier.

  • Name
    variantKey
    Type
    string
    Description

    Stable key within the product, e.g. "flexible", "locked-90d", "tier-platinum".

  • Name
    name
    Type
    string | null
    Description

    Provider's display name for the offer.

  • Name
    termType
    Type
    string | null
    Description

    flexible, fixed, etc.

  • Name
    termDays
    Type
    integer | null
    Description

    Lockup length in days for fixed terms.

  • Name
    tierName
    Type
    string | null
    Description

    Loyalty or balance tier the offer applies to.

  • Name
    minDeposit
    Type
    number | null
    Description

    Minimum deposit, in minDepositCurrency.

  • Name
    minDepositCurrency
    Type
    string | null
    Description

    Currency of minDeposit.

  • Name
    maxEligibleBalance
    Type
    number | null
    Description

    Balance above which the rate stops applying.

  • Name
    requiredToken
    Type
    string | null
    Description

    Token that must be held to qualify (e.g. a platform token).

  • Name
    requiredTokenAmount
    Type
    number | null
    Description

    Quantity of requiredToken needed.

  • Name
    rewardAsset
    Type
    string | null
    Description

    Asset the yield is paid in, when it differs from the deposited asset.

  • Name
    compounding
    Type
    string | null
    Description

    Compounding cadence, e.g. daily, none.

  • Name
    payoutFrequency
    Type
    string | null
    Description

    How often rewards are paid, e.g. daily, weekly, at_maturity.

  • Name
    withdrawalNoticeDays
    Type
    integer | null
    Description

    Notice period before funds can be withdrawn.

  • Name
    kycRequired
    Type
    boolean | null
    Description

    Whether identity verification is required.

  • Name
    promotional
    Type
    boolean
    Description

    true when the offer is a time-limited promotion.

  • Name
    promotionExpiresAt
    Type
    string | null
    Description

    ISO 8601 expiry of the promotion, when known.

  • Name
    tvlUsd
    Type
    number | null
    Description

    On-chain TVL in USD for DeFi variants.

  • Name
    riskLevel
    Type
    string | null
    Description

    Provider- or reviewer-assigned risk label.

  • Name
    collectionMethod
    Type
    string
    Description

    Baseline collection method for the variant: pull_api, push, onchain, websocket, multi_source, manual, provider_confirmed, backfill, or unknown.

  • Name
    confidence
    Type
    integer | null
    Description

    0–100 variant-level confidence score.

  • Name
    confidenceBand
    Type
    string
    Description

    Derived from confidence: high (≥ 80), medium (50–79), low (< 50), or unknown when no score.

  • Name
    lastVerifiedAt
    Type
    string | null
    Description

    ISO 8601 instant a human or provider last verified the terms.

  • Name
    verifiedBy
    Type
    string | null
    Description

    Who verified: a reviewer handle or the provider.

  • Name
    fieldProvenance
    Type
    object | null
    Description

    Per-field overrides of the baseline provenance — see Confidence and provenance. Served verbatim.

  • Name
    effectiveGeo
    Type
    object
    Description

    Resolved geographic eligibility — see Geo resolution.

  • Name
    metadata
    Type
    object | null
    Description

    Provider-specific extras, served verbatim.

  • Name
    lastObservedAt
    Type
    string
    Description

    ISO 8601 instant the variant was last seen.


Geo resolution

Each variant carries an effectiveGeo object so you never have to merge provider-level and offer-level restrictions yourself. Resolution is: if the variant declares its own allow or block list, use that (source: "variant"); otherwise fall back to the provider's country lists (source: "provider"); if neither exists, both lists are null and source is "none".

effectiveGeo

{
  "allowed": null,
  "blocked": ["US", "GB", "CA"],
  "source": "provider"
}

allowed and blocked are arrays of ISO 3166-1 alpha-2 codes or null. An allowed list means only those countries; a blocked list means everywhere except those countries. source: "none" means we have no eligibility data, not that the offer is available everywhere.


Confidence and provenance

Every variant has a baseline collectionMethod and confidence. When individual fields were captured differently — the lockup was provider-attested but the fee schedule was parsed from a web page, say — fieldProvenance records the override per field. The object is keyed by variant field name and served exactly as stored:

fieldProvenance

{
  "termDays": {
    "source": "provider_portal",
    "method": "provider_confirmed",
    "verified_at": "2026-09-02T09:14:00Z",
    "confidence": 100
  },
  "minDeposit": {
    "source": "https://example-provider.com/earn/terms",
    "method": "manual",
    "verified_at": "2026-08-28T16:40:00Z",
    "confidence": 80
  }
}

A method of provider_confirmed means the provider attested to the value through Bitcompare's attestation programme, which is activating now; the Coverage endpoint reports how many providers and variants are attested at any time.


GET/api/v1/earn/products

List products

Paginated list of products with their active variants, ordered by provider, symbol, category.

Optional attributes

  • Name
    provider
    Type
    string
    Description

    Restrict to one provider slug.

  • Name
    symbol
    Type
    string
    Description

    Restrict to one asset symbol.

  • Name
    category
    Type
    string
    Description

    lending, borrowing, or staking.

  • Name
    status
    Type
    string
    Description

    active (default), inactive, or delisted.

  • Name
    minConfidence
    Type
    integer
    Description

    0–100. Only return products with at least one active variant at or above this confidence.

  • Name
    includeVariants
    Type
    string
    Description

    true (default) or false. Omit the variants array for a lighter response.

  • Name
    limit
    Type
    integer
    Description

    Page size, 1–200. Defaults to 50.

  • Name
    offset
    Type
    integer
    Description

    Zero-based offset for paging. Defaults to 0.

Response

{ data: { products, pagination } }. pagination carries total, limit, offset, and hasMore. Responses are Cache-Control: private, max-age=60.

Request

GET
/api/v1/earn/products
# BITCOMPARE_API_KEY is your ck_live_… key from https://pro.bitcompare.net/dashboard/keys
curl -G https://api.bitcompare.net/api/v1/earn/products \
  -H "Authorization: Bearer $BITCOMPARE_API_KEY" \
  -d provider=nexo \
  -d symbol=BTC \
  -d category=lending

Response

{
  "data": {
    "products": [
      {
        "id": 4182,
        "provider": "nexo",
        "symbol": "BTC",
        "category": "lending",
        "coinId": "bitcoin",
        "platformType": "cefi",
        "status": "active",
        "firstObservedAt": "2026-07-21T00:57:15.412Z",
        "lastObservedAt": "2026-09-16T02:30:04.118Z",
        "variants": [
          {
            "id": 9931,
            "variantKey": "flexible",
            "name": "Flexible",
            "termType": "flexible",
            "termDays": null,
            "tierName": null,
            "minDeposit": null,
            "minDepositCurrency": null,
            "maxEligibleBalance": null,
            "requiredToken": null,
            "requiredTokenAmount": null,
            "rewardAsset": "BTC",
            "compounding": "daily",
            "payoutFrequency": "daily",
            "withdrawalNoticeDays": 0,
            "kycRequired": true,
            "promotional": false,
            "promotionExpiresAt": null,
            "tvlUsd": null,
            "riskLevel": null,
            "collectionMethod": "pull_api",
            "confidence": 85,
            "confidenceBand": "high",
            "lastVerifiedAt": null,
            "verifiedBy": null,
            "fieldProvenance": null,
            "effectiveGeo": {
              "allowed": null,
              "blocked": ["US"],
              "source": "provider"
            },
            "metadata": {},
            "lastObservedAt": "2026-09-16T02:30:04.118Z"
          },
          {
            "id": 9932,
            "variantKey": "locked-90d-platinum",
            "name": "Fixed 90 days — Platinum",
            "termType": "fixed",
            "termDays": 90,
            "tierName": "Platinum",
            "minDeposit": null,
            "minDepositCurrency": null,
            "maxEligibleBalance": null,
            "requiredToken": "NEXO",
            "requiredTokenAmount": null,
            "rewardAsset": "NEXO",
            "compounding": "none",
            "payoutFrequency": "at_maturity",
            "withdrawalNoticeDays": null,
            "kycRequired": true,
            "promotional": false,
            "promotionExpiresAt": null,
            "tvlUsd": null,
            "riskLevel": null,
            "collectionMethod": "manual",
            "confidence": 80,
            "confidenceBand": "high",
            "lastVerifiedAt": "2026-08-28T16:40:00.000Z",
            "verifiedBy": "reviewer:bitcompare-ops",
            "fieldProvenance": {
              "termDays": {
                "source": "https://nexo.com/earn-crypto",
                "method": "manual",
                "verified_at": "2026-08-28T16:40:00Z",
                "confidence": 80
              }
            },
            "effectiveGeo": {
              "allowed": null,
              "blocked": ["US"],
              "source": "provider"
            },
            "metadata": {},
            "lastObservedAt": "2026-09-16T02:30:04.118Z"
          }
        ]
      }
    ],
    "pagination": {
      "total": 1,
      "limit": 50,
      "offset": 0,
      "hasMore": false
    }
  }
}

GET/api/v1/earn/products/:id

Get a product

One product by id, with variants of every status (a delisted product's history is still data). Works for inactive and delisted products that the list endpoint's default status=active filter would hide.

Path parameters

  • Name
    id
    Type
    integer
    Description

    The product's id from the list endpoint.

Response

{ data: { product } } with the same product shape as the list endpoint. Responses are Cache-Control: private, max-age=60.

Request

GET
/api/v1/earn/products/4182
# BITCOMPARE_API_KEY is your ck_live_… key from https://pro.bitcompare.net/dashboard/keys
curl https://api.bitcompare.net/api/v1/earn/products/4182 \
  -H "Authorization: Bearer $BITCOMPARE_API_KEY"

Response

{
  "data": {
    "product": {
      "id": 4182,
      "provider": "nexo",
      "symbol": "BTC",
      "category": "lending",
      "coinId": "bitcoin",
      "platformType": "cefi",
      "status": "active",
      "firstObservedAt": "2026-07-21T00:57:15.412Z",
      "lastObservedAt": "2026-09-16T02:30:04.118Z",
      "variants": [ "…same variant shape as the list endpoint…" ]
    }
  }
}

Errors

  • Name
    403 PLAN_UPGRADE_REQUIRED
    Description

    No key, or a key on a plan without Earn Intelligence (Free, Starter, Growth). The body carries feature: "intelligence" and an absolute upgradeUrl.

  • Name
    404 NOT_FOUND
    Description

    No product with that id.

  • Name
    422 VALIDATION_ERROR
    Description

    id not a positive integer, limit outside 1–200, minConfidence outside 0–100, or an unknown category/status.

  • Name
    429 RATE_LIMIT_EXCEEDED
    Description

    Plan per-minute budget exhausted. See Rate Limiting.

The full error envelope is described on the Errors page.

403 PLAN_UPGRADE_REQUIRED

{
  "error": {
    "message": "Earn Intelligence endpoints require a Pro or Enterprise plan.",
    "code": "PLAN_UPGRADE_REQUIRED",
    "feature": "intelligence",
    "upgradeUrl": "https://pro.bitcompare.net/pricing"
  }
}

See also

Was this page helpful?