> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dripstack.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Stock Picks

> GET /api/v2/stock-picks — ticker-level analyst calls by day or date range, by subscription or per-request payment.

A **stock pick** is a ticker-level call extracted from a source — an analyst
recommendation, a long/short idea, an add, or an exit. Drip serves these as
structured JSON for AI agents, separate from the newsletter/article workflow.

| Route | Access |
| - | - |
| `GET /api/v2/stock-picks` | Subscription (PRO/EXPERT), credits, or x402 pay-per-use |
| `GET /api/v2/stock-picks/quote` | Free, no auth |

## `GET /api/v2/stock-picks`

Resolves the caller's plan from the bearer credential first, then either serves
the request from the subscription window **free of charge** or routes anonymous
/ FREE callers through the pay-per-use flow.

### Subscription access (Bearer API key, OAuth token, or session JWT)

* **EXPERT** readers get full history. **PRO** is clamped to the live 7-day
  window.
* In-plan requests are **never charged** and count against the API key's monthly
  request allowance (`429` when exhausted).
* An explicit `date` outside the plan window returns `403`; out-of-window ranges
  are clamped. A PRO range with no overlap returns `403` — read
  `meta.allowedRange` / `meta.appliedRange`.

```bash theme={null}
# Latest picks in-window (free for PRO/EXPERT subscribers)
curl -H "Authorization: Bearer pk_drip_..." \
  "https://dripstack.com/api/v2/stock-picks"

# Historical range (EXPERT); 3 days per page, sorted oldest-first within each page
curl -H "Authorization: Bearer pk_drip_..." \
  "https://dripstack.com/api/v2/stock-picks?from=2026-05-01&to=2026-05-31&sort=oldest&limitDays=3"
```

### Pay-per-use (anonymous or FREE)

No free API access. Call the free quote, confirm the `amountUsd`, then pay with
an x402 client or a bearer credential backed by Drip credits. Freeze the quote's
`dateUsed` and use the same `limit` on the paid request. The paid path selects
one day using `date` / `limit`; `sort` orders that day's rows. Ranges,
author / direction / query filters, pagination, and prices apply to
subscription reads and are ignored on the paid path.

Bundles are charged per request. A purchase does not create a lifetime post
unlock.

```bash theme={null}
# 1. Free preflight — inspect amountUsd and dateUsed before approving payment
curl "https://dripstack.com/api/v2/stock-picks/quote?date=2026-05-30&limit=200"

# 2. After approval, use the returned dateUsed and the same limit
curl -H "Authorization: Bearer $DRIP_API_KEY" \
  "https://dripstack.com/api/v2/stock-picks?date=2026-05-30&limit=200"
```

### Query parameters

| Param | Meaning |
| - | - |
| `date` | One UTC day (mutually exclusive with `from`/`to`) |
| `from` / `to` | Inclusive UTC day range, clamped to the caller's plan window |
| `limit` | Max pick rows per day (1-500, default 200) |
| `limitDays` | Max days per range page (1-30, default 7); pass `cursor` to page older |
| `cursor` | Older-than marker from the previous response's `pagination.nextCursor` |
| `author` | Exact author name filter (paid tiers) |
| `query` | Case-insensitive substring over ticker, author, and publication title (paid tiers) |
| `sort` | `newest` (default) or `oldest` within each page; pages always move toward older days |
| `includePrices` | Pass `false` to omit prices; otherwise historical subscriber picks may include verified asset prices |

### Response envelope

Three top-level keys, always present:

| Key | Contents |
| - | - |
| `meta` | Serving mode and the window you actually got |
| `pagination` | `count` (rows returned) and `nextCursor` (`null` on the last page) |
| `picks` | Flat pick rows, sorted within the page by `sort` |

`meta.plan` is `FREE`, `PRO`, `EXPERT`, or `PAID` (pay-per-use). `meta.allowedRange`
is the plan's full window — `null` for EXPERT full history and for PAID requests.
`meta.appliedRange` is your request intersected with that window. `meta.asOf` is
the server timestamp. `meta.requestAllowance` is the plan's monthly allowance,
`null` when paid.

### Pick fields

| Field | Notes |
| - | - |
| `date` | UTC calendar day of the pick |
| `ticker`, `tickerExchange`, `instrumentType` | As extracted; `instrumentType` is the legacy type, prefer `asset` |
| `assetId`, `assetResolutionStatus`, `asset` | Resolved identity; `null` until resolved |
| `action` | `NEW_POSITION`, `ADD`, `HOLD`, `RECOMMENDATION`, `REDUCE`, `EXIT`, or `OPINION` |
| `author`, `publicationSlug`, `publicationTitle` | Who made the call and where |
| `articleUrl` | Drip's paid route for the source article, when a post is attributed |
| `conviction`, `convictionLabel` | Author confidence, 0-5, plus a label |
| `evidenceQuote` | Verbatim quote supporting the extracted pick |
| `thesis` | Generated summary of the author's reasoning — not a quote |
| `sentiment` | `BULLISH`, `BEARISH`, or `NEUTRAL` |
| `rationaleSnippet` | Short rationale summary |
| `publishedAt` | ISO timestamp, may be `null` |
| `prices` | Present on historical subscriber reads only — see below |

`assetResolutionStatus` is `RESOLVED`, `UNRESOLVED`, or `PENDING`. `asset` carries
`id`, `name`, `kind` (`EQUITY`/`ETF`/`CRYPTO`), `symbol`, `exchangeMic`,
`currency`. A ticker alone can refer to different assets — key on `assetId`.

`prices` carries `entry`, `current`, `returnPct`, `currency`, with `returnPct`
adjusted for the author's direction. Prices are omitted for the current day,
pay-per-use requests, `includePrices=false`, unresolved assets, and unavailable
or mismatched provider data.

### Example — subscriber read (one day)

```bash theme={null}
curl -s \
  "https://dripstack.com/api/v2/stock-picks?date=2026-05-30&limit=200" \
  -H "Authorization: Bearer $DRIP_API_KEY"
```

```json theme={null}
{
  "meta": {
    "plan": "EXPERT",
    "allowedRange": null,
    "appliedRange": { "from": "2026-05-30", "to": "2026-05-30" },
    "requestAllowance": 50000,
    "asOf": "2026-05-31T00:05:12.482Z"
  },
  "pagination": { "count": 3, "nextCursor": null },
  "picks": [
    {
      "date": "2026-05-30",
      "ticker": "NVDA",
      "tickerExchange": "NASDAQ",
      "instrumentType": "EQUITY",
      "assetId": "asset_9f2c1d",
      "assetResolutionStatus": "RESOLVED",
      "asset": {
        "id": "asset_9f2c1d",
        "name": "NVIDIA Corporation",
        "kind": "EQUITY",
        "symbol": "NVDA",
        "exchangeMic": "XNAS",
        "currency": "USD"
      },
      "action": "ADD",
      "author": "Example Analyst",
      "publicationSlug": "example-finance-newsletter.com",
      "publicationTitle": "Example Finance Newsletter",
      "articleUrl": "https://dripstack.com/api/v1/publications/example-finance-newsletter.com/nvda-position-review",
      "conviction": 4,
      "convictionLabel": "high",
      "evidenceQuote": "Adding to my NVDA position on the pullback — datacenter revenue is still running ahead of consensus.",
      "thesis": "The author adds to an existing long after a ~12% drawdown, arguing forward AI capex guidance from hyperscalers supports another leg up.",
      "sentiment": "BULLISH",
      "rationaleSnippet": "Add to existing long; AI capex estimates still rising while the stock de-rated.",
      "publishedAt": "2026-05-30T11:24:07.000Z",
      "prices": { "entry": 121.44, "current": 128.9, "returnPct": 6.15, "currency": "USD" }
    },
    {
      "date": "2026-05-30",
      "ticker": "SMCI",
      "tickerExchange": "NASDAQ",
      "instrumentType": "EQUITY",
      "assetId": null,
      "assetResolutionStatus": "PENDING",
      "asset": null,
      "action": "NEW_POSITION",
      "author": "Another Writer",
      "publicationSlug": "second-publication.com",
      "publicationTitle": "Second Publication",
      "articleUrl": "https://dripstack.com/api/v1/publications/second-publication.com/smci-new-position",
      "conviction": 2,
      "convictionLabel": "low",
      "evidenceQuote": "Opening a small SMCI position here; rack margins are inflecting and the backlog is not priced in.",
      "thesis": null,
      "sentiment": "BULLISH",
      "rationaleSnippet": null,
      "publishedAt": "2026-05-30T09:02:55.000Z"
    },
    {
      "date": "2026-05-30",
      "ticker": "BTC-USD",
      "tickerExchange": null,
      "instrumentType": "CRYPTO",
      "assetId": "asset_7b41ee",
      "assetResolutionStatus": "RESOLVED",
      "asset": {
        "id": "asset_7b41ee",
        "name": "Bitcoin",
        "kind": "CRYPTO",
        "symbol": "BTC-USD",
        "exchangeMic": null,
        "currency": "USD"
      },
      "action": "OPINION",
      "author": "Third Writer",
      "publicationSlug": null,
      "publicationTitle": null,
      "articleUrl": "https://third-writer.substack.com/p/btc-position-review",
      "conviction": 3,
      "convictionLabel": "medium",
      "evidenceQuote": "Still structurally bullish bitcoin, but I would not add above this level until the ETF flows turn.",
      "thesis": "The author expresses a directional view without framing it as a trade, so no entry or exit is extracted.",
      "sentiment": "BULLISH",
      "rationaleSnippet": "Structural bullishness, waiting on ETF flows before adding.",
      "publishedAt": "2026-05-30T13:41:20.000Z"
    }
  ]
}
```

### Example — range page (EXPERT, prices omitted for the current day)

```bash theme={null}
curl -s \
  "https://dripstack.com/api/v2/stock-picks?from=2026-05-01&to=2026-05-31&sort=oldest&limitDays=3" \
  -H "Authorization: Bearer $DRIP_API_KEY"
```

```jsonc theme={null}
{
  "meta": {
    "plan": "EXPERT",
    "allowedRange": null,
    // A PRO plan would clamp here instead: requested range ∩ 7-day window.
    "appliedRange": { "from": "2026-05-01", "to": "2026-05-03" },
    "requestAllowance": 50000,
    "asOf": "2026-05-31T00:05:12.482Z",
  },
  "pagination": {
    "count": 512,
    // Pass this as ?cursor= to get days strictly before 2026-05-01.
    "nextCursor": "2026-05-01",
  },
  "picks": [/* 512 rows across 2026-05-01 → 2026-05-03 */],
}
```

Fetch the next page with the cursor and the same window:

```bash theme={null}
curl -s \
  "https://dripstack.com/api/v2/stock-picks?from=2026-05-01&to=2026-05-31&sort=oldest&limitDays=3&cursor=2026-05-01" \
  -H "Authorization: Bearer $DRIP_API_KEY"
```

### Example — filtered read

`author` and `query` apply to subscription reads. They match the author exactly
and substring-match ticker, author, and publication title respectively.

```bash theme={null}
curl -s \
  "https://dripstack.com/api/v2/stock-picks?date=2026-05-30&query=nvda&author=Example%20Analyst" \
  -H "Authorization: Bearer $DRIP_API_KEY"
```

```jsonc theme={null}
{
  "meta": {
    "plan": "EXPERT",
    "allowedRange": null,
    "appliedRange": { "from": "2026-05-30", "to": "2026-05-30" },
    "requestAllowance": 49997,
    "asOf": "2026-05-31T00:05:12.482Z",
  },
  "pagination": { "count": 1, "nextCursor": null },
  "picks": [/* the single NVDA pick above */],
}
```

### Example — empty day

A valid day with no picks is a `200`, not an error. Do not pay on an empty
bundle.

```json theme={null}
{
  "meta": {
    "plan": "PRO",
    "allowedRange": { "from": "2026-05-25", "to": "2026-05-31" },
    "appliedRange": { "from": "2026-05-30", "to": "2026-05-30" },
    "requestAllowance": 50000,
    "asOf": "2026-05-31T00:05:12.482Z"
  },
  "pagination": { "count": 0, "nextCursor": null },
  "picks": []
}
```

### Quote response

`GET /api/v2/stock-picks/quote` is free and returns no pick rows — it prices the
bundle. `dateUsed` is the day that will actually be charged; freeze it and reuse
the same `limit` on the paid request.

```bash theme={null}
curl "https://dripstack.com/api/v2/stock-picks/quote?date=2026-05-30&limit=200"
```

```json theme={null}
{
  "dateUsed": "2026-05-30",
  "startDate": "2026-05-30",
  "endDate": "2026-05-30",
  "asOf": "2026-05-31T00:05:12.482Z",
  "count": 184,
  "attributedPostCount": 37,
  "amountUsd": "1.85",
  "posts": [
    { "publicationSlug": "example-finance-newsletter.com", "amountUsd": "0.05" },
    { "publicationSlug": "second-publication.com", "amountUsd": "0.05" },
    { "publicationSlug": null, "amountUsd": "0.05" }
  ]
}
```

`404` means nothing to buy for that day — stop, do not pay. Prices are per
source post; the bundle total is the sum of `posts[].amountUsd`.

### Errors

`400` invalid query, `401` bad bearer, `402` payment required, `403` outside the
plan window or insufficient credits, `404` no picks (paid path), `429` request
allowance exhausted.

| Status | Body | Action |
| - | - | - |
| `400` | `{ error, code, hint, issues }` | Fix the query — `date` with `from`/`to`, `from` after `to` |
| `401` | `{ error, code, hint }` | Check the bearer token |
| `403` | `{ error, code, hint }` — date or range outside the plan window | Re-read `meta.allowedRange` from a successful call and stay inside it |
| `404` | `{ error, code, hint }` | No picks that day; do not pay |
| `429` | `{ error, code, hint }` | Monthly allowance exhausted; retry next cycle |

## Hosted MCP

| MCP tool | HTTP route | Paid? |
| - | - | - |
| `quote_stock_picks_v2` | `GET /api/v2/stock-picks/quote` | Free, no auth |
| `list_stock_picks_v2` | `GET /api/v2/stock-picks` | OAuth/API key required; subscribers free, others spend credits (`confirmSpend: true`) |

`list_stock_picks_v2` requires an API key or OAuth token with `mcp:unlock`;
anonymous wallet payments use HTTP instead. On the paid path, call the quote
tool first, show `amountUsd` as `$X.XX`, confirm with the user, then call
`list_stock_picks_v2` with `confirmSpend: true`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.