All pages

Daily recap

GET /v1/recap

The daily recap email for a day, in full: every story, X post, video and investor letter it listed, by section. Without day, the newest recap, ordinarily yesterday's. Any other parameter is refused.

Parameters

ParameterTypeDescription
daystringThe recap for this day, as YYYY-MM-DD in New York time. Leave it out for the newest recap, ordinarily yesterday's. It must be a real date, and not after today.
sectionstring, 1 to 100 charactersOnly this section of the recap, by its name. Spaces at either end don't count, and it can't contain a null character.
curl "https://api.bullpen.news/v1/recap?day=2026-10-30&section=Materials" \
  -H "Authorization: Bearer $BULLPEN_KEY"
import os, requests

r = requests.get(
    "https://api.bullpen.news/v1/recap",
    params={"day": "2026-10-30", "section": "Materials"},
    headers={"Authorization": f"Bearer {os.environ['BULLPEN_KEY']}"},
)
r.raise_for_status()
print(r.json())
const r = await fetch('https://api.bullpen.news/v1/recap?day=2026-10-30&section=Materials', {
	headers: { Authorization: `Bearer ${process.env.BULLPEN_KEY}` }
});
if (!r.ok) throw new Error((await r.json()).detail);
console.log(await r.json());

What comes back

FieldTypeDescription
daystring (date)The day the recap covers, YYYY-MM-DD in New York time. Without a day in the call, the newest recap.
subjectstringThe email's subject line.
headlinestringThe email's preview line, shown under the subject in an inbox.
bullpenUrlstringThe recap on bullpen.news.
sectionsarray of objectThe email's sections in its order, or only the one asked for. Anything taken off bullpen.news since it was sent is left out.
sections[].namestringThe section as the email headed it, such as Technology and AI.
sections[].resultsarray of Story, XPost, Video or LetterIts stories, X posts, videos and investor letters, in the order the email listed them.
tickersmap of TickerEntryEach company the results name, by ticker.
HeaderSent withDescription
Request-Idevery answerThis request's id, such as req_ followed by 24 letters and digits. Quote it to support.
RateLimit-Policy200, 400, 404, 429, 500, 503Your plan's quotas, per minute and per day (IETF draft-11). It may change to match the RFC.
RateLimit200, 400, 404, 429, 500, 503What each window has left, and the seconds until it resets (IETF draft-11).
WWW-Authenticate401Bearer realm="bullpen.news"
Retry-After429, 503How many seconds to wait.

GET /v1/recap?day=2026-10-30&section=Materials

{
  "day": "2026-10-30",
  "subject": "Bullpen.News, Friday October 30th: 92 stock ideas",
  "headline": "92 stock ideas from 20 stories, 33 X posts and 8 investor letters.",
  "bullpenUrl": "https://bullpen.news/recap/2026-10-30",
  "sections": [
    {
      "name": "Materials",
      "results": [
        {
          "id": "x:5274458",
          "kind": "x_post",
          "postId": "2116317834792034350",
          "url": "https://x.com/i/web/status/2116317834792034350",
          "published": "2026-10-30T23:54:25Z",
          "wentLive": "2026-10-30T23:56:13Z",
          "companies": [
            "ELMT"
          ]
        }
      ]
    }
  ],
  "tickers": {
    "ELMT": {
      "name": "Elmet Group Co.",
      "sector": "Materials",
      "marketCapUsd": 688080000,
      "bullpenUrl": "https://bullpen.news/ticker/ELMT"
    }
  }
}

Status codes

StatusMeaningCodes
200The answer.
400A parameter is invalid or unknown (invalid_request), a key is in the URL (key_in_url), or a cursor is not this call's (invalid_cursor).key_in_url, invalid_request, invalid_cursor
401No valid key (unauthorized), or a revoked one (revoked).unauthorized, revoked
403Your account can't use this endpoint now: invite, disabled, terms, no_plan, ended, unpaid or tool.no_plan, ended, unpaid, terms, disabled, invite, tool
404Nothing by that ticker, firm, id or day (not_found).not_found
429Your plan's minute or day limit is reached (minute, day).minute, day
500Something went wrong on bullpen.news (internal).internal
503The API is paused (off), busy (ceiling) or having trouble (unavailable). Retry-After comes with all but off.ceiling, off, unavailable

Fresh: The newest recap goes out each morning. A past day never changes.
History: Every day from 7 September 2026.
Cost: One call, for the whole issue.