> ## 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.

# Available credit balance and top-up URLs.

> Returns spendable balance across active signup and top-up credit pools plus lifetime purchased/spent totals and `topUpUrl` / `dashboardUrl`. Expired credits are excluded. Lifetime purchased totals include purchases and promos, not signup grants. Requires bearer API key or OAuth access token with `mcp:unlock`. Session JWTs are rejected. There is no top-up API — send users to `topUpUrl`.



## OpenAPI

````yaml https://dripstack.com/openapi.json get /api/v1/me/credits
openapi: 3.1.0
info:
  title: Drip
  summary: Premium financial newsletter and podcast API with micropayment access.
  version: 0.1.0
  description: >
    Paid API for searching and browsing Drip's premium financial newsletters and
    podcasts, resolving publications and direct post links, and purchasing
    synthesized post summaries for investing research and market analysis.


    ## Payment Flow


    Paid routes return HTTP 402 with a dual challenge. Use an x402 payment-aware
    client; MPP works on V1 paid routes.


    1. Plain request returns 402 with `WWW-Authenticate` (MPP) and
    `PAYMENT-REQUIRED` (x402) headers.

    2. Retry the same request through a payment-aware client, or manually with
    `Authorization: Payment <credential>` (MPP) or `PAYMENT-SIGNATURE` header
    (x402).

    3. On success (200), response includes `synthesizedSummary`, `transcript`
    for podcast episodes, and `paymentInfo`. The first successful pay for a
    single post unlocks that post forever for the paying subject; later fetches
    are free. Credits / API key / JWT / MCP OAuth share one Drip-user
    entitlement. x402/MPP clients should store `unlockToken` / `X-Drip-Unlock`
    for free re-reads.


    **Pricing:** Discovery `x-payment-info.offers[]` is advisory. Runtime 402
    challenge is authoritative. Stock-picks charge a flat unit
    (`STOCK_PICKS_ARTICLE_PRICE_USD`) times distinct source article count — use
    free `GET /api/v1/stock-picks/quote` (or `/api/v2/stock-picks/quote`) for
    the exact bundle total; live `402` on the paid route remains authoritative
    for payment clients. Stock-picks remain pay-per-request (no forever unlock).


    **Error codes:** 402 = payment required, do not retry without payment. 503 =
    summary not ready, retry later. 404 = content not found, do not pay.


    **JSON errors:** Non-402 error responses use `{ error, code, hint }`.
    `error` is the human message (stable for existing clients); `code` is
    machine-readable; `hint` points at recovery (often `/openapi.json` or
    `/llms.txt`).
  contact:
    name: Drip
    email: support@dripstack.com
    url: https://dripstack.com
  license:
    name: Proprietary
    url: https://dripstack.com/terms
  x-guidance: >
    # Drip API Reference


    ## Discovery


    Prefer `GET /openapi.json` (OpenAPI 3.1) for route shapes, JSON schemas, and
    paid-route `x-payment-info.offers[]` metadata. If OpenAPI is unavailable,
    use `GET /.well-known/x402` for the paid resource list in `METHOD /path`
    form.


    Root `x-discovery.ownershipProofs` is a Drip vendor extension, not part of
    core MPP discovery.


    ## Hosted MCP


    Streamable HTTP MCP server at `/api/mcp` (Next.js route `/api/[transport]`
    with transport `mcp`). Tools mirror the public V1 and V2 routes:


    - `search_posts` → topic search (free)

    - `search_entities` → article search by
    ticker/company/person/organization/subject or canonical author, with
    optional stock-pick-only filtering and earliest/latest sorting (free)

    - `search_companies` → company identity by ticker, domain, qid, CIK, or name
    (free)

    - `get_company` → one company profile by id (free)

    - `list_publications` → curated catalog (free; only when browsing the
    catalog)

    - `search_publications` → publication name search (free)

    - `get_publication` → publication metadata + recent post list (free)

    - `list_podcasts` → curated podcast catalog (free; only when browsing
    podcasts)

    - `get_podcast` → podcast metadata + recent episode list (free; 404 unless
    the slug is a podcast — otherwise `get_publication`)

    - `list_top_selling_posts` → most purchased posts as free post cards (only
    when the user asks for popular or top-selling posts)

    - `list_top_selling_publications` → highest-earning publications (only when
    the user asks for popular or top-selling publications)

    - `quote_stock_picks` → free preflight price for a UTC day's stock-picks
    bundle (`amountUsd`) — V1 (still available)

    - `quote_stock_picks_v2` → same free preflight for the V2 API, no auth —
    prefer for new integrations

    - `get_account` → auth introspection for the current API key or OAuth token
    (no user ids)

    - `get_credits_balance` → available credit balance plus `topUpUrl` /
    `dashboardUrl`

    - `list_credit_activity` → cursor-paginated credit ledger rows

    - `list_unlocked_posts` → cursor-paginated posts this account already
    unlocked (metadata only)

    - `unlock_post` → paywalled `synthesizedSummary` (plus podcast `transcript`
    when available) via Drip credits (OAuth or API key); confirm the
    `priceCents` charge with the user, then call with `confirmSpend: true`
    (rejected without it)

    - `list_stock_picks` → paid structured stock picks for a UTC day via Drip
    credits (OAuth or API key); call `quote_stock_picks` first, show
    `amountUsd`, confirm, then call with `confirmSpend: true` (rejected without
    it) — V1 (still available)

    - `list_stock_picks_v2` → Stock Picks API V2: Pro/Expert callers are served
    within their plan window with no charge and no `confirmSpend`; authenticated
    callers without a paid plan spend Drip credits after `quote_stock_picks_v2`
    + `confirmSpend: true`. Supports ranges, filters, and pagination — prefer
    for new integrations


    Prompts (invoke via prompts/get for the full runbook; tool descriptions stay
    short blurbs for tools/list):


    - `research-topic` — arg `topic` → `search_posts` → present with price →
    confirm → `unlock_post` with `confirmSpend: true` → show podcast
    `transcript` when present, otherwise `synthesizedSummary` + Source lines

    - `browse-publication` — arg `nameOrUrl` → `search_publications` →
    `get_publication` → confirm → optional `unlock_post` with `confirmSpend:
    true`

    - `list-stock-picks` — optional arg `date` → `quote_stock_picks` → show
    `amountUsd` → confirm → `list_stock_picks` with `confirmSpend: true` → table
    + dig-deeper → article unlocks with the same confirmation


    Server `instructions` always include the spend-confirmation and
    evidence/stop rules. Paid tools are annotated `destructiveHint: true` and
    require MCP-only `confirmSpend: true` (in-app chat schemas omit the flag).


    Resources (read-only context hosts can attach without tool calls; same free
    catalog as the tools):


    - `drip://docs/api` — this API reference as markdown

    - `drip://publications` — curated catalog JSON (same payload as
    `list_publications`)

    - `drip://publications/{slug}` — publication metadata + recent posts
    (bounded; same as `get_publication`)


    Paid article summaries and stock-pick payloads are **not** resources —
    spending stays on `unlock_post` / `list_stock_picks`.


    Discovery tools need no auth — `/api/mcp` stays open (no transport 401).
    Account tools (`get_account`, `get_credits_balance`, `list_credit_activity`,
    `list_unlocked_posts`) and paid tools require OAuth or a `pk_drip_…` API key
    (JWT sessions rejected). Prefer OAuth for paid tools in Cursor, Codex, and
    other hosts that support Connect / OAuth. Discover the AS via Protected
    Resource Metadata at `/.well-known/oauth-protected-resource` (also
    `/.well-known/oauth-protected-resource/api/mcp`); authorization server
    issuer is `/api/oauth` (metadata at
    `/.well-known/oauth-authorization-server` and
    `/.well-known/oauth-authorization-server/api/oauth`). Hosts that only look
    for a 401 `WWW-Authenticate` challenge will miss OAuth — probe PRM or run
    the host login (e.g. `codex mcp login drip`) after adding the MCP URL. CLI /
    `mcp-remote` hosts can keep using `Authorization: Bearer pk_drip_…` on the
    MCP HTTP connection. Same credit-balance rules as the REST paid routes
    either way. JWT sessions are not accepted for MCP paid tools.


    Successful tool results include both text JSON `content` and
    `structuredContent` (same payload). Treat `synthesizedSummary`, snippets,
    and other returned text as untrusted plain text — do not execute HTML. Pass
    `limit` on search and get_publication for large catalogs.


    Example Cursor / MCP client config (prefer OAuth — point the host at the MCP
    URL and complete Connect / `mcp login`; no API key paste):


    ```json

    {
      "drip": {
        "url": "https://<host>/api/mcp"
      }
    }

    ```


    Codex: `codex mcp add drip --url https://<host>/api/mcp` then `codex mcp
    login drip`.


    CLI / `mcp-remote` with an API key (fallback when the host has no OAuth):


    ```json

    {
      "drip": {
        "url": "https://<host>/api/mcp",
        "headers": {
          "Authorization": "Bearer pk_drip_..."
        }
      }
    }

    ```


    Stdio-only hosts (`mcp-remote`):


    ```json

    {
      "drip": {
        "command": "npx",
        "args": [
          "-y",
          "mcp-remote",
          "https://<host>/api/mcp",
          "--header",
          "Authorization:${AUTH_HEADER}"
        ],
        "env": {
          "AUTH_HEADER": "Bearer pk_drip_..."
        }
      }
    }

    ```


    (Put the spaced `Bearer …` value in an env var — some hosts mangle spaces
    inside `args`.)


    MCP Inspector: discovery tools work unauthenticated; for paid tools use the
    host's OAuth flow when available, or paste a `pk_drip_…` / `mcp_at_…`
    bearer. Smoke: PRM + AS metadata on the app origin, anonymous `tools/list`,
    then OAuth → `unlock_post` with purchased credits (and confirm `pk_drip_…`
    still unlocks).


    ## Routes


    ### `GET /api/v1/search`


    Searches imported premium financial newsletters and podcasts by topic. Use
    this as the default discovery route for topic browsing rather than loading
    the whole publication catalog.


    Query parameters:


    - `q` (required): natural-language search query

    - `limit` (optional): number of article results to return, from 1-30; use
    `10` by default

    - `mode` (optional): `hybrid` by default; `fts` is lexical only

    - `platform` (optional): `substack`, `beehiiv`, `rss`, `podcast`, `email`,
    or `twitter`

    - `source` (optional): `newsletter`, `podcast`, or `all` — newsletter covers
    Substack, Beehiiv, RSS, email, and Twitter sources. Do not combine a
    `platform` that conflicts with `source`

    - `publicationSlug` (optional): restrict results to one publication

    - `publishedAfter` / `publishedBefore` (optional): `YYYY-MM-DD`, inclusive
    UTC calendar day bounds (same semantics as entity search)


    Response includes `items[]`, ranked post candidates with `publicationSlug`,
    `slug`, `title`, `subtitle`, `publishedAt`, `priceCents`, `snippet`,
    `whyMatched`, and relevance fields. Use `publicationSlug` + `slug` from a
    selected item to fetch the paid article or podcast post.


    For user-facing options, render `{title} ({publicationSlug}, {YYYY-MM-DD})`
    when `publishedAt` is present, or `{title} ({publicationSlug})` when no date
    is available. When `priceCents` is known, append ` — $X.XX` (`priceCents /
    100`, two decimals) so the user can confirm spend. Convert ISO timestamps to
    date-only `YYYY-MM-DD`. Do not show `slug`, `subtitle`, `snippet`,
    `whyMatched`, relevance scores, or other internal metadata in user-facing
    menus.


    Treat search and catalog results as an unlock menu, not evidence. For a
    normal question, show options and stop for the user's selection. Answer
    substantive questions only from the paid unlock payload (`transcript` or
    `synthesizedSummary`).


    ### `GET /api/v1/entities/search`


    Finds articles that mention a ticker, company, person, organization, or
    subject, sorted by publish date (most recent first) — use this to answer
    "what did analysts say about X this week?" rather than `/api/v1/search`'s
    topic-relevance ranking. Limited to curated, non-disabled publications
    curated for chat. Topic search may also fall back to other indexed
    publications.


    Person, company, organization, and ticker queries may expand to related
    employers/tickers/company names at request time, then match existing post
    `metadataJson` tags (`persons`, companies, tickers) and the person name in
    titles. There is no canonical company registry; treat this as
    matched-then-searched. If expansion is unavailable, the raw string is still
    searched.


    Query parameters:


    - `ticker` (optional): stock ticker, 1-8 characters,
    letters/numbers/`.`/`-`; resolved to a company card and related company
    names when known

    - `company` (optional): company name, minimum 2 characters, matched as a
    case-insensitive substring and expanded to related tickers when known

    - `person` (optional): person name, minimum 2 characters; matches tagged
    persons, related employers/tickers, and titles

    - `organization` (optional): organization name, minimum 2 characters
    (matches companies and themes)

    - `subject` (optional): theme/subject, minimum 2 characters, matched against
    post metadata themes

    - `author` (optional): canonical source author, minimum 2 characters,
    matched as a case-insensitive substring

    - `stockPicksOnly` (optional): `true` restricts articles to stock-pick
    sources; with `ticker`, matches the pick ticker exactly without entity
    expansion

    - `sort` (optional): `latest` (default) or `earliest`

    - at least one of `ticker`, `company`, `person`, `organization`, `subject`,
    or `author` is required

    - `publicationSlug` (optional): restrict results to one publication

    - `publishedAfter` / `publishedBefore` (optional): `YYYY-MM-DD`, inclusive
    UTC calendar day bounds

    - `limit` (optional): 1-30, defaults to 10

    - `cursor` (optional): pass the previous response's `nextCursor` to fetch
    the next page


    Response includes `query` (the normalized filters used), optional
    `matchedEntity` (the person, company, or organization matched from the
    query, with `companies`, `tickers`, and `matchedVia`), `count`,
    `nextCursor`, and `items[]` with `publicationSlug`, `slug`, `title`,
    `author`, `publishedAt`, `priceCents`, `url`, and `isPodcast`. `priceCents`
    is the price to unlock the full article via the existing paid
    publication-post route; no payment is required for this search itself.
    `isPodcast` is true for podcast episodes — the paid post response then
    includes a `transcript` when ready.


    ### `GET /api/v1/companies`


    Looks up a company identity card by ticker, domain, qid, CIK, or name. This
    is not article search — use `GET /api/v1/entities/search` after you have a
    ticker to find mentioning articles.


    Query parameters:


    - `ticker` (optional): stock ticker, 1-8 characters, letters/numbers/`.`/`-`

    - `domain` (optional): official website host, e.g. `nvidia.com`

    - `qid` (optional): company id, e.g. `Q182477`

    - `cik` (optional): SEC CIK, 1-10 digits

    - `name` (optional): company name, minimum 2 characters, used when no other
    identifier is known

    - at least one of `ticker`, `domain`, `qid`, `cik`, or `name` is required

    - when more than one identifier is given, lookup uses `qid` > `ticker` >
    `domain` > `cik` > `name` to find candidates; the remaining identifiers must
    also match

    - `limit` (optional): 1-10, defaults to 5


    Response includes `query` (the normalized filters used), `count`, and
    `items[]` with `id`, `name`, `description`, and `identifiers` (`ticker`,
    `domain`, `cik`, `qid`). Empty matches return `200` with `items: []`.
    Unexpected lookup failures return `500`. Present `name` plus
    `identifiers.ticker` / `domain` to users — do not lead with raw ids.


    ### `GET /api/v1/companies/{companyId}`


    Returns one company profile (same object as a list item) by `id` from the
    list route. Returns `404` when the id is unknown or is not a company.


    ### `GET /api/v1/publications`


    Lists curated newsletters, podcasts, and publications with `slug`, `title`,
    `description`, `siteUrl`, and `lastSyncedAt`. Use this only when the user
    explicitly wants to browse the curated catalog or asks what publications are
    available.


    ### `GET /api/v1/publications/search`


    Searches curated publications by slug, title, author, podcast show,
    newsletter, or site URL. Required query parameter: `q` (minimum 2
    characters). Returns up to 3 matches with `publicationSlug`, `title`,
    `author`, and `siteUrl`.


    ### `GET /api/v1/publications/{publicationSlug}`


    Returns publication metadata plus `posts`: post summaries with `slug`,
    `title`, `subtitle`, `publishedAt`, and `priceCents`. Works for any enabled
    indexed publication by slug (not limited to the curated list). Returns `404`
    if the publication is missing or disabled.


    Optional post-list query parameter: `limit` (1-100). Omit it to return all
    posts with a ready summary.


    ### `GET /api/v1/podcasts`


    Lists curated podcasts with `slug`, `title`, `description`, `siteUrl`, and
    `lastSyncedAt`. Same JSON envelope as `GET /api/v1/publications` (`{
    publications: [...] }`). Use this only when the user explicitly wants to
    browse podcasts.


    ### `GET /api/v1/podcasts/{publicationSlug}`


    Returns podcast metadata plus `posts`: episode summaries with `slug`,
    `title`, `subtitle`, `publishedAt`, `priceCents`, and `isPodcast`. Returns
    `404` if the slug is missing, disabled, or not a podcast. Unlock episodes
    with `GET /api/v1/publications/{publicationSlug}/{postSlug}` (same paid post
    route as newsletters).


    Optional episode-list query parameter: `limit` (1-100). Omit it to return
    all episodes with a ready summary.


    ### `GET /api/v1/posts/top-selling`


    Lists the most purchased posts as free post cards. Use this only when the
    user asks for popular, top-selling, or most-purchased articles.


    Optional query parameter: `limit` (1-100, default 10).


    Response includes `items[]` with `publicationSlug`, `slug`, `title`,
    `subtitle`, `publishedAt`, `priceCents`, `isPodcast`, `purchaseCount`, and
    `totalAmountSoldUsd`. Unlock selected posts with `GET
    /api/v1/publications/{publicationSlug}/{postSlug}`.


    ### `GET /api/v1/publications/top-selling`


    Lists the highest-earning publications. Use this only when the user asks for
    popular or top-selling publications.


    Optional query parameter: `limit` (1-100, default 10).


    Response includes `totals` (`articlePurchaseCount`, `totalAmountSoldUsd`)
    and `publications[]` with `slug`, `title`, `description`, `siteUrl`,
    `articlePurchaseCount`, `purchasedArticleCount`, and `totalAmountSoldUsd`.
    After the user chooses a publication, call `GET
    /api/v1/publications/{publicationSlug}` then unlock selected posts with the
    paid publication-post route.


    ### `GET /api/v1/publications/{publicationSlug}/{postSlug}` (paid)


    Returns post metadata and `synthesizedSummary` after payment. Podcast
    episodes also include `transcript` when ready. Returns `404` if the
    publication or post is not found, `503` with code `summary_not_ready` when
    the summary is not ready yet (retry later; no payment challenge), and `402`
    if payment is required. See Payment for auth and the unpaid challenge.


    ### `GET /api/v1/stock-picks/quote`


    Free preflight for the paid stock-picks route. Same `date` / `limit`
    validation as the paid list. Returns `dateUsed`, `amountUsd` (exact bundle
    total), `attributedPostCount`, and `posts[]` with `publicationSlug` and
    per-post `amountUsd`. Does not return pick rows, tickers, or evidence.
    Returns `404` when no picks exist for the requested or resolved day.


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


    Returns stock-picker calls for AI-agent consumption after payment.


    **V1 — still available.** Keep using it if you already integrate against V1;
    it is unchanged. New integrations and new code should target `GET
    /api/v2/stock-picks` below (subscription access, date ranges, filters,
    search, and pagination; same bundle pricing on the paid path). This is a
    specialized paid route for ticker-level picks, analyst calls,
    recommendations, and investment ideas; it is not part of the normal
    newsletter/podcast search, selection, and paid-summary workflow.


    This endpoint always returns one effective UTC calendar day, not a rolling
    date range. By default, it returns the latest day that has stock picks. Pass
    `date=YYYY-MM-DD` to request one effective UTC day. After calling the free
    quote, agents must pass the quoted `dateUsed` on the paid request. Optional
    `limit` is 1-500 and defaults to 200. Call the free quote route first to
    learn `amountUsd` before paying.


    The effective day is based on article `publishedAt`; when publication time
    is missing, the server may use extraction time internally. Returned items do
    not include extraction time, so treat `publishedAt` as source article
    context only and omit date context when it is null.


    Response includes `dateUsed`, `startDate`, `endDate`, `asOf`, `count`, and
    `items[]`. `dateUsed` is the canonical returned day; `startDate` and
    `endDate` are the same as `dateUsed` for this single-day response. Each item
    includes `ticker`, `tickerExchange`, `instrumentType`, `action`,
    `direction`, `authorConviction`, `convictionLabel`, `activePick`,
    `evidenceQuote`, `rationaleSnippet`, `articleTitle`, `articleUrl`, `author`,
    `publishedAt`, `publicationSlug`, and `postSlug`.


    Returns `404` when no stock picks exist for the requested or resolved day —
    do not pay on `404`. Plain requests return `402` only when matching paid
    picks exist. Runtime price is a flat unit (`STOCK_PICKS_ARTICLE_PRICE_USD`)
    times the number of distinct attributed source articles in the returned
    picks — call `/stock-picks/quote` for the exact total. After settlement, the
    server records a sale for each distinct attributed source article.


    ### `GET /api/v2/stock-picks` (preferred over V1)


    Tier-aware stock picks for AI-agent consumption. This is the recommended
    endpoint for stock-picker calls, analyst recommendations, and ticker-level
    long/short ideas — prefer it over `/api/v1/stock-picks`, which stays
    available unchanged for existing integrations.


    **Subscription (Bearer `pk_drip_…` API key, OAuth, or session JWT):** the
    caller's plan resolves first. 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). Explicit out-of-window `date` returns `403`; PRO ranges are
    clamped and return `403` if there is no overlap — read `meta.allowedRange` /
    `meta.appliedRange`.


    **Anonymous / FREE:** no free API access — anonymous HTTP callers use x402,
    while authenticated callers without a paid plan spend Drip credits, priced
    at the flat unit times distinct attributed source articles. Call `GET
    /api/v2/stock-picks/quote`, confirm the `amountUsd`, then pay. The paid path
    uses `date`/`limit` and `sort`; subscription-only filters, ranges,
    pagination, and prices are ignored.


    Query parameters:


    - `date=YYYY-MM-DD` — one UTC calendar day (mutually exclusive with
    `from`/`to`; `400` if combined)

    - `from` / `to` — inclusive UTC day range (clamped to the caller's plan
    window)

    - `limit` (1-500, default 200) — max pick rows per day

    - `limitDays` (1-30, default 7) — max days per range page; pass `cursor` to
    page older

    - `cursor` — older-than marker from `pagination.nextCursor`

    - `author` — exact author name filter (paid tiers)

    - `direction` — `LONG` or `SHORT` (paid tiers)

    - `query` — case-insensitive substring over ticker, author, publication
    title (paid tiers)

    - `sort` — `newest` (default) or `oldest` within each page; range pagination
    always continues toward older days

    - `includePrices` — pass `false` to omit prices; historical subscription
    reads may include verified asset prices


    Response includes `meta` (`plan`, `allowedRange`, `appliedRange`,
    `requestAllowance`, `asOf`), `pagination` (`count`, `nextCursor`), and
    `picks[]` with `date`, `ticker`, `direction`, `action`, `author`,
    `publicationSlug`, `publicationTitle`, `articleUrl` (Drip sellable URL when
    a post is attributed), `conviction`, `convictionLabel`, `evidenceQuote`,
    `rationaleSnippet`, `publishedAt`, and `tickerExchange` / `instrumentType`,
    plus `assetId`, `assetResolutionStatus`, and nullable `asset` for resolved
    identity. Historical subscription reads may include `prices` (`entry` /
    `current` / `returnPct` / `currency`, direction-adjusted). Prices are
    omitted on the current day, paid requests, unresolved identities, or
    unavailable/mismatched provider data.


    Errors: `400` invalid query, `401` bad bearer, `402` payment required, `403`
    explicit date/range outside the plan window, `404` no picks (paid path),
    `429` request allowance exhausted.


    ### `GET /api/v2/stock-picks/quote` (free, no auth)


    Free preflight for the V2 paid flow — same price logic and response shape as
    the V1 quote. Returns `dateUsed`, `amountUsd` (exact bundle total),
    `attributedPostCount`, and `posts[]` (`publicationSlug`, per-post
    `amountUsd`; no post slugs or pick rows). Returns `404` when no picks exist
    for the requested or resolved day.


    ### `GET /api/v1/me`


    Auth introspection for the current bearer credential. Requires
    `Authorization: Bearer pk_drip_…` or OAuth `mcp_at_…` with `mcp:unlock`.
    Session JWTs are rejected. Returns `authMethod`, `apiKey` (`name`/`suffix`
    for API keys; null for OAuth), and `scopes` (OAuth scopes; null for API
    keys). Never returns raw keys or user ids.


    ### `GET /api/v1/me/credits`


    Available credit balance for the current agent actor. Same auth as
    `/api/v1/me`. Returns `purchasedBalanceUsd` (legacy field name for all
    active, unexpired credit pools), `lifetimePurchasedUsd` (purchases/promos
    only; excludes signup grants), `lifetimeSpentUsd`, `topUpUrl`, and
    `dashboardUrl`. There is no top-up API — send users to `topUpUrl` when
    balance is too low for a paid unlock.


    ### `GET /api/v1/me/credits/activity`


    Cursor-paginated credit ledger for the current agent actor. Same auth as
    `/api/v1/me`. Optional `limit` (1-50, default 20) and `cursor`. Each item
    includes `id`, `kind`, `amountUsd`, `balanceAfterUsd`, `feature`,
    `description`, `packageId`, `promoCode`, and `createdAt`, plus `nextCursor`.


    ### `GET /api/v1/me/unlocks`


    Cursor-paginated lifetime unlocks for the current agent actor. Same auth as
    `/api/v1/me`. Optional `limit` (1-50, default 20) and `cursor`. Each item
    includes `id`, `publicationSlug`, `publicationName`, `postSlug`, `title`,
    `subtitle`, `author`, `url`, `publishedAt`, `unlockedAt`, `isPodcast`, and
    `amountUsd`, plus `nextCursor`. Does not include `synthesizedSummary` —
    re-read with the paid publication-post route / `unlock_post` (free after the
    first unlock).


    ## Payment


    Prefer Hosted MCP OAuth when available. Wallet clients settle the live `402`
    (x402; MPP on V1 paid routes); API-key clients send `Authorization: Bearer
    pk_drip_…` and debit Drip credits (no x402/MPP handshake).


    Unpaid responses include a dual payment challenge: MPP in `WWW-Authenticate:
    Payment ...` and x402 v2 in `PAYMENT-REQUIRED`. Retry the same request with
    `PAYMENT-SIGNATURE` for x402 v2, or `Authorization: Payment ...` for MPP on
    V1 paid routes. If plain HTTP returns `402`, retry the same request through
    a payment-aware client instead of treating it as a final failure.


    Infer the live price from the paid endpoint response or payment challenge.
    OpenAPI `x-payment-info.offers[]` is advisory and may show Base or Solana
    USDC x402, Tempo, and Stripe charges or catalog floor prices; per-post
    pricing comes from the runtime challenge. Wallet clients trust the live
    `402` challenge over discovery offers; API-key clients use discovery
    `priceCents` or quote `amountUsd`.


    Paid HTTP routes do not take a confirmation flag. Ask the user, then call
    the paid GET. `confirmSpend: true` is MCP-only (`unlock_post` /
    `list_stock_picks`); it is required for first post unlocks and paid
    stock-pick requests. Existing post unlocks and in-plan V2 subscription reads
    do not need it.


    ## Agent flows


    ### Topic search


    Use when the user asks a general finance question, asks what writers or
    podcasts are saying, or wants article/podcast post recommendations.


    1. Call `GET /api/v1/search?q={query}&limit=10`.

    2. Present returned `items[]` with title, publication slug, date, and
    `$X.XX` when `priceCents` is known.

    3. Keep each candidate's `publicationSlug` and `slug` for the paid fetch
    URL, and `priceCents` for spend confirmation.

    4. Fetch selected article summaries with `GET
    /api/v1/publications/{publicationSlug}/{postSlug}` after confirmation.

    5. Show purchased podcast `transcript` when present; otherwise answer only
    from fetched `synthesizedSummary` text.


    ### Company identity


    Use when the user asks who a ticker, domain, or company is — not what
    analysts wrote about it.


    1. Call `GET /api/v1/companies` with `ticker`, `domain`, `qid`, `cik`, or
    `name`.

    2. Present `name` plus `identifiers.ticker` / `domain`. Keep `id` internally
    for `GET /api/v1/companies/{companyId}`.

    3. If the user then wants articles, call `GET /api/v1/entities/search` with
    the ticker and show article options as usual.


    ### Specific publication


    Use when the user names a publication, author, podcast show, newsletter, or
    shares a Substack publication URL.


    1. Call `GET /api/v1/publications/search?q={query}` unless the normalized
    slug is obvious.

    2. If one match is clearly right, call `GET
    /api/v1/publications/{publicationSlug}`.

    3. Present 3-5 recent post titles from `posts[]` with date and `$X.XX` when
    `priceCents` is known.

    4. Show `$X.XX` from `priceCents` and confirm before paying, then fetch
    selected post summaries through the paid post route.


    ### Browse catalog


    Use when the user asks to see available newsletters, podcasts, or
    publications before choosing one.


    1. Call `GET /api/v1/publications`.

    2. Present publications as `Publication Title (slug) — short description`.

    3. After the user chooses a publication, call `GET
    /api/v1/publications/{publicationSlug}`.

    4. Show `$X.XX` from `priceCents` and confirm before paying, then fetch
    selected post summaries through the paid post route.


    ### Popular posts


    Use when the user asks for popular, top-selling, or most-purchased articles.


    1. Call `GET /api/v1/posts/top-selling`.

    2. Present returned `items[]` with title, publication slug, date, and
    `$X.XX` when `priceCents` is known.

    3. Keep each candidate's `publicationSlug`, `slug`, and `priceCents` for the
    paid fetch.

    4. Show `$X.XX` and confirm before paying, then fetch selected post
    summaries through the paid post route.


    ### Popular publications


    Use when the user asks for popular or top-selling publications.


    1. Call `GET /api/v1/publications/top-selling`.

    2. Present publications as `Publication Title (slug) — short description`.

    3. After the user chooses a publication, call `GET
    /api/v1/publications/{publicationSlug}`.

    4. Show `$X.XX` from `priceCents` and confirm before paying, then fetch
    selected post summaries through the paid post route.


    ### Stock picks


    Use when the user asks for stock-picker calls, stock recommendations, recent
    investment picks, analyst calls, or ticker-level long/short ideas.


    **Prefer V2** (`/api/v2/stock-picks` + `/api/v2/stock-picks/quote`, or MCP
    `list_stock_picks_v2` / `quote_stock_picks_v2`) — subscribers read within
    their plan window free of charge, and the paid path mirrors V1 pricing. V1
    (and `list_stock_picks` / `quote_stock_picks`) remains available.


    For V2 with a subscription (Bearer):


    1. Call `GET /api/v2/stock-picks/quote` (free) for a specific
    `?date={YYYY-MM-DD}`, or skip the quote entirely and call `GET
    /api/v2/stock-picks` (live window) / with `from`+`to` (bounded by the plan —
    read `meta.appliedRange`).

    2. Apply `author`, `direction`, `query`, `sort`, and `limitDays`/`cursor`
    pagination as the ask requires. Filters are paid-tier features.

    3. Present picks with ticker, direction, author, date, and
    direction-adjusted return when `prices` is present.


    For V2 pay-per-use (anonymous / FREE) or V1:


    1. Call the free quote (`/api/v2/stock-picks/quote` or
    `/api/v1/stock-picks/quote`) for the latest UTC effective day with picks, or
    `?date={YYYY-MM-DD}` for a specific day. Read `dateUsed` and `amountUsd`.
    Pass the same `limit` you will use on the paid request.

    2. Show the quoted `amountUsd` as `$X.XX` and confirm the user wants to
    spend that amount before paying.

    3. Call the paid list after confirmation, using the quoted `dateUsed` as
    `date` and the same `limit` supplied on the quote. Prefer Hosted MCP
    `list_stock_picks_v2` / `list_stock_picks` with `confirmSpend: true` (after
    the matching quote tool) when available.

    4. If either response is `404`, no picks exist for that day — do not pay;
    try another date or tell the user none are available.

    5. Present picks as ticker, call (action), conviction, analyst, rationale,
    and source. Do not expose `publicationSlug`, `postSlug`, `evidenceQuote`, or
    other internal fields unless the user asks.

    6. Treat `publishedAt` as the article publication time; if it is null, omit
    date context rather than inventing one.

    7. After presenting successful stock-pick results, always ask: `Want to dig
    deeper into any of these picks and the authors' reasoning behind them?` If
    the user selects one or more picks, for V1 use each pick's `publicationSlug`
    and `postSlug` to offer the corresponding source article; for V2 use its
    Drip `articleUrl`. Follow article unlock confirmation (exact `priceCents`
    charge) before fetching. If using Hosted MCP, call `unlock_post` with
    `confirmSpend: true`.


    ### Direct article


    Use when the user shares a direct article URL, podcast post URL, or a
    specific post slug.


    1. Resolve `publicationSlug` and `postSlug` from the URL or context.

    2. Prefer Hosted MCP `unlock_post` with `confirmSpend: true` when available.

    3. Wallet clients: probe the paid endpoint unpaid to inspect the live `402`
    challenge and price. API-key clients: read `priceCents` from a free
    publication post list or prior discovery — do not send the Bearer key until
    confirmed.

    4. Show `$X.XX` and confirm before paying, then call `GET
    /api/v1/publications/{publicationSlug}/{postSlug}`.


    ## Fetched article response handling


    When `transcript` is non-null, display the full purchased podcast transcript
    in the conversation rather than linking to an episode page. Otherwise answer
    only from `synthesizedSummary`. For one article, return a rich curated
    summary (synthesis, notable claims, caveats, implications, source context).
    For multiple articles, compare claims, mechanisms, tensions, caveats, and
    implications across sources. Append one source line per fetched article:
    `Source: {Title} — {Publication}, {date if available} — {URL if available}`.
    Never use a page URL as a stand-in for purchased `transcript`. If a paid
    fetch fails, surface the failure rather than substituting model knowledge.
    If some selected articles succeed and others fail, synthesize only from
    successfully fetched articles and name the failed fetches.


    Runtime pricing note: paid post challenges use the stored per-post USD price
    when present, else at least $1.
servers:
  - url: https://dripstack.com
security: []
tags:
  - name: Search
    description: Search premium newsletters and podcasts by topic.
  - name: Companies
    description: Look up company identity by ticker, domain, qid, CIK, or name.
  - name: Publications
    description: List, search, and import newsletters, podcasts, and publications.
  - name: Podcasts
    description: List curated podcasts and fetch episode summaries.
  - name: Posts
    description: Fetch, unlock, and list article summaries and podcast transcripts.
  - name: Stock Picks
    description: >-
      Daily stock-picker calls, analyst recommendations, and investment ideas.
      Two API versions: V2 (`/api/v2/stock-picks` + `/api/v2/stock-picks/quote`)
      is recommended — Bearer Pro/Expert subscribers read within their plan
      window for free (ranges, filters, search, pagination), anonymous callers
      pay via x402 and authenticated callers without a paid plan spend Drip
      credits after a free quote. V1 (`/api/v1/stock-picks` +
      `/api/v1/stock-picks/quote`) is the legacy pay-per-use single-day flow,
      still available unchanged for existing integrations.
  - name: Daily Brief
    description: >-
      Daily market brief as markdown for one UTC calendar date. Pay-per-date via
      x402/MPP or Drip credits; the first paid read caches the brief per paying
      subject and later reads are free.
  - name: Account
    description: >-
      Agent account introspection: auth context, available credit balance, and
      credit activity. Requires bearer API key (`pk_drip_…`) or OAuth access
      token (`mcp_at_…` with `mcp:unlock`). Session JWTs are rejected.
paths:
  /api/v1/me/credits:
    get:
      tags:
        - Account
      summary: Available credit balance and top-up URLs.
      description: >-
        Returns spendable balance across active signup and top-up credit pools
        plus lifetime purchased/spent totals and `topUpUrl` / `dashboardUrl`.
        Expired credits are excluded. Lifetime purchased totals include
        purchases and promos, not signup grants. Requires bearer API key or
        OAuth access token with `mcp:unlock`. Session JWTs are rejected. There
        is no top-up API — send users to `topUpUrl`.
      operationId: getMeCredits
      responses:
        '200':
          description: Credit balance snapshot.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeCreditsResponse'
        '401':
          description: >-
            Missing or invalid bearer credentials, or an unsupported session
            JWT.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '403':
          description: Valid OAuth access token missing the required `mcp:unlock` scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
      security:
        - apiKey: []
        - oauth2:
            - mcp:unlock
components:
  schemas:
    MeCreditsResponse:
      type: object
      additionalProperties: false
      required:
        - purchasedBalanceUsd
        - lifetimePurchasedUsd
        - lifetimeSpentUsd
        - topUpUrl
        - dashboardUrl
      properties:
        purchasedBalanceUsd:
          type: number
          description: >-
            Current pooled credit balance in USD, including signup and purchased
            credits.
        lifetimePurchasedUsd:
          type: number
          description: Lifetime USD added via purchases or promos (excludes signup grants).
        lifetimeSpentUsd:
          type: number
          description: Lifetime USD spent from the pooled credit balance.
        topUpUrl:
          type: string
          format: uri
          description: URL where the user can buy more credits.
        dashboardUrl:
          type: string
          format: uri
          description: Credits dashboard URL.
      example:
        purchasedBalanceUsd: 4.25
        lifetimePurchasedUsd: 20
        lifetimeSpentUsd: 15.75
        topUpUrl: https://dripstack.com/pricing
        dashboardUrl: https://dripstack.com/billing
    ErrorMessage:
      type: object
      additionalProperties: false
      required:
        - error
        - code
        - hint
      properties:
        error:
          type: string
          description: Human-readable error message.
        code:
          type: string
          description: >-
            Machine-readable error code (e.g. not_found, bad_request,
            summary_not_ready).
        hint:
          type: string
          description: >-
            Short recovery guidance for agents (often points at /openapi.json or
            /llms.txt).
        reason:
          type: string
          description: Optional domain-specific reason (e.g. insufficient_credits on 403).
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: API Key
      description: >-
        Bearer API key (`pk_drip_…`) or OAuth access token (`mcp_at_…`). Session
        JWTs are rejected on routes that require this scheme.
    oauth2:
      type: oauth2
      description: >-
        MCP OAuth authorization-code flow (PKCE). Access tokens are `mcp_at_…`
        bearers; request scope `mcp:unlock`. Discovery:
        https://dripstack.com/.well-known/oauth-authorization-server and
        https://dripstack.com/.well-known/openid-configuration (issuer
        https://dripstack.com/api/oauth).
      flows:
        authorizationCode:
          authorizationUrl: https://dripstack.com/api/oauth/authorize
          tokenUrl: https://dripstack.com/api/oauth/token
          refreshUrl: https://dripstack.com/api/oauth/token
          scopes:
            mcp:unlock: Unlock paid posts and credit-gated MCP/API tools

````

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