Developer API
Sentinel API
Score institutional and media language for deontic pressure, epistemic certainty, entropy, and drift versus a public baseline — programmatically. Every response is a signed, reproducible receipt. Get a key in your dashboard.
Data sources
From the dashboard Analyze home, search or pick a source chip for a guided pull. Capability: fetch (Sentinel can load the URL), guided (Reader / Connect), or paste (text or screenshot only). The public API always takes text — there is no server-side URL fetch on /api/v1/analyze.
Federal Reserve (fetch)
Score FOMC statements and press materials against the Fed baseline.
Can Sentinel complete this pull? Yes — load from link or Fed Drift archive
- Open Fed Drift for a meeting, or paste a federalreserve.gov URL.
- On Analyze / Ingest, use Load from link (or prefilled Fed Drift CTA).
- Confirm entity is Federal Reserve, then Analyze.
- Or POST text to /api/v1/analyze with entity Federal Reserve.
Dashboard: /fed-drift
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"FOMC statement","text":"The Committee decided to maintain the target range for the federal funds rate. The Committee is strongly committed to returning inflation to its 2 percent objective.","sourceOutlet":"Federal Reserve","entity":"Federal Reserve","voiceSegment":"institutional","contentKind":"article","sourceUrl":"https://www.federalreserve.gov/newsevents/pressreleases/monetary20260128a.htm"}'URL fetch runs in the dashboard. The public API accepts text only — paste the statement body.
U.S. Congress (fetch)
Institutional segment for congressional speech and committee materials.
Can Sentinel complete this pull? Yes — load from .gov link when public
- Paste a congress.gov or .gov transcript URL into Analyze.
- Load from link, set entity to U.S. Congress if needed.
- Analyze, or send extracted text via the API.
Dashboard: /dashboard/ingest?entity=U.S.%20Congress
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Committee hearing excerpt","text":"The Chair recognizes the gentlelady from California. We must ensure that regulators have the authority to supervise these institutions.","sourceOutlet":"U.S. Congress","entity":"U.S. Congress","voiceSegment":"institutional","contentKind":"plain"}'Reuters (fetch)
Public Reuters articles usually fetch server-side.
Can Sentinel complete this pull? Often — public pages via Load from link
- Paste the reuters.com article URL into the Analyze search box.
- Choose Analyze now to load and score.
- If fetch fails, paste the article body instead.
Dashboard: /dashboard/ingest
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Reuters article","text":"Paste the full article body here when calling the API. Dashboard Load from link can fetch public Reuters pages.","sourceOutlet":"Reuters","voiceSegment":"journalist_obligation","contentKind":"article"}'Dashboard can fetch the URL. /api/v1/analyze requires the article text in the body.
BBC (fetch)
Public BBC News pages often work with Load from link.
Can Sentinel complete this pull? Often — public pages via Load from link
- Paste a bbc.com/news URL into Analyze.
- Analyze now — or paste text if the fetch is blocked.
Dashboard: /dashboard/ingest
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"BBC article","text":"Paste the full article body here when calling the API.","sourceOutlet":"BBC","voiceSegment":"journalist_obligation","contentKind":"article"}'NPR (fetch)
Public NPR stories often fetch successfully.
Can Sentinel complete this pull? Often — public pages via Load from link
- Paste an npr.org URL into Analyze and run Analyze now.
- Fallback: paste transcript or article text.
Dashboard: /dashboard/ingest
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"NPR story","text":"Paste the full story or transcript body here when calling the API.","sourceOutlet":"NPR","voiceSegment":"journalist_obligation","contentKind":"article"}'Bloomberg (guided)
Paywalled. Capture from your logged-in browser via Blackhorse Reader.
Can Sentinel complete this pull? Guided — Reader or paste (no server pull)
- Install Blackhorse Reader (Chrome zip or Safari app) from the Reader tab.
- Connect your Sentinel account in the extension.
- Open the Bloomberg article while logged in → Analyze this page.
- Or paste / screenshot on Ingest. Do not expect Load from link to work.
Dashboard: /dashboard/reader
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Bloomberg article","text":"Paste article text extracted by Reader or by hand. Server-side URL fetch will not retrieve paywalled Bloomberg content.","sourceOutlet":"Bloomberg","voiceSegment":"journalist_obligation","contentKind":"article"}'Extension uses POST /api/v1/capture (OAuth) or /api/v1/analyze (API key) with extracted text.
Wall Street Journal (guided)
Paywalled. Use Reader on a logged-in WSJ tab.
Can Sentinel complete this pull? Guided — Reader or paste (no server pull)
- Install and connect Blackhorse Reader.
- Open the WSJ article logged in → Analyze this page.
- Or paste the article text on Ingest.
Dashboard: /dashboard/reader
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"WSJ article","text":"Paste article text from Reader or manual copy. URL fetch will not bypass the paywall.","sourceOutlet":"Wall Street Journal","voiceSegment":"journalist_obligation","contentKind":"article"}'Financial Times (guided)
Paywalled. Use Reader or paste.
Can Sentinel complete this pull? Guided — Reader or paste (no server pull)
- Connect Blackhorse Reader, open the FT article logged in, Analyze.
- Or paste on Ingest.
Dashboard: /dashboard/reader
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"FT article","text":"Paste article text from Reader or manual copy.","sourceOutlet":"Financial Times","voiceSegment":"journalist_obligation","contentKind":"article"}'The Economist (guided)
Paywalled. Use Reader or paste.
Can Sentinel complete this pull? Guided — Reader or paste (no server pull)
- Connect Blackhorse Reader, open the Economist article logged in, Analyze.
- Or paste on Ingest.
Dashboard: /dashboard/reader
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Economist article","text":"Paste article text from Reader or manual copy.","sourceOutlet":"The Economist","voiceSegment":"journalist_obligation","contentKind":"article"}'Screenshot / social (paste)
Upload a screenshot of a social post; OCR extracts text for scoring.
Can Sentinel complete this pull? Paste-only — OCR screenshot on Ingest
- Open Ingest (or drop an image on Analyze).
- Upload PNG/JPEG of the post; OCR runs in the browser.
- Confirm outlet (X, LinkedIn, …) and Analyze.
Dashboard: /dashboard/ingest
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Social screenshot","text":"Paste OCR’d post text here for API calls. Dashboard screenshot upload runs OCR client-side.","sourceOutlet":"Social screenshot","voiceSegment":"journalist_obligation","contentKind":"screenshot"}'There is no screenshot upload on /api/v1/analyze — send the OCR text with contentKind: screenshot.
Paste text (paste)
Fastest path when you already have the text.
Can Sentinel complete this pull? Paste-only — any source
- Paste ≥100 characters into the Analyze search box and submit.
- Or use the classic Ingest form textarea.
- API: POST /api/v1/analyze with text.
Dashboard: /dashboard/ingest
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Untitled analysis","text":"Paste at least one hundred characters of institutional or media language to score.","voiceSegment":"journalist_obligation","contentKind":"plain"}'Podcast RSS (fetch)
Pull show notes or episode description from an RSS or episode URL.
Can Sentinel complete this pull? Yes — Load from link on RSS / episode pages
- Paste the episode or feed URL into Analyze.
- Load from link extracts description / show notes when available.
- Prefer a transcript paste for full scoring.
Dashboard: /dashboard/ingest
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Podcast episode","text":"Paste the episode transcript or show notes. RSS fetch may only return a short description.","voiceSegment":"podcast","contentKind":"podcast"}'Raw text API (paste)
Programmatic scoring with an API key from the dashboard.
Can Sentinel complete this pull? API — POST /api/v1/analyze
- Create a key under API keys.
- POST JSON with text (≥100 chars) to /api/v1/analyze.
- Read the signed receipt and reportId from the response.
Dashboard: /dashboard/api-keys
curl -sS -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer bhs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"API sample","text":"The Committee is prepared to adjust the stance of monetary policy as appropriate if risks emerge that could impede the attainment of the Committee's goals.","entity":"Federal Reserve","voiceSegment":"institutional","contentKind":"plain"}'Ingest modes (dashboard)
Load from link fetches and extracts text server-side for public / institutional URLs. Paste (or Blackhorse Reader) is required for paywalled publishers. Prefer the Analyze search box for find / paste / source pull; use classic Ingest for the full form.
Social screenshots (contentKind: "screenshot"): OCR text is tagged as body / chrome / marketing; only the post body is scored. Platforms detected include X, TikTok, Truth Social, Instagram, LinkedIn, and others.
Video / audio (Pro / Enterprise): upload a clip on Analyze — Whisper transcribes it (local whisper.cpp, then Cloudflare Workers AI), then the transcript is scored as a normal run. Remote YouTube/Vimeo URLs are not fetched; news pages with a video embed still ingest when enough article text is present.
Social Drift (Pro / Enterprise, dashboard only at /dashboard/social-drift): org-scoped platform baselines and a historical index. Not a public page. Pro is limited to a 90-day window; Enterprise is full history.
Blackhorse Reader extension
The Reader extension extracts articles from Bloomberg, WSJ, FT, and Economist while you are logged in on the publisher site. Extraction runs locally in your browser; text is sent to Sentinel only when you click Analyze.
Download: /downloads/blackhorse-reader-chrome.zip. Unzip → chrome://extensions → Developer mode → Load unpacked. Not on the Chrome Web Store or Mac App Store yet. Setup guide: Dashboard → Reader.
Connect via OAuth in the extension popup, or save a bhs_live_… API key. OAuth uses /api/v1/capture and counts against dashboard ingest quota. API keys use /api/v1/analyze and count against API quota.
Authentication
All requests use a Bearer API key over HTTPS. Keys are secret and server-side only — never embed them in a browser or mobile client. Pass the key in the Authorization header (or x-api-key).
https://blackhorsesentinel.com/api/v1
Authorization: Bearer bhs_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Quotas & tiers
API calls are metered per calendar month against your plan. When you exceed the quota the API returns 402 quota_exceeded.
Endpoints
POST /analyze
Score a document and store a report. Body fields: text (required), title, sourceOutlet, entity, author, sourceUrl, voiceSegment, contentKind (article | podcast | pdf | plain | screenshot).
Pass entity matching corpus baseline keys exactly — e.g. Federal Reserve, European Central Bank, U.S. Congress, European Commission.
curl -X POST https://blackhorsesentinel.com/api/v1/analyze \
-H "Authorization: Bearer $SENTINEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "FOMC statement",
"sourceOutlet": "FEDERAL_RESERVE",
"entity": "Federal Reserve",
"text": "The Committee will continue to assess..."
}'{
"id": "9c2f...",
"tier": "HIGH",
"score": { "deonticScore": 0.42, "dominantDeontic": "obligation", "avgEpistemicScore": 0.61, ... },
"drift": { "driftScore": 0.18, "baseline": { "entity": "Federal Reserve", "source": "corpus", ... } },
"receipt": { "receiptId": "...", "sha256": "...", "signature": "...", "signedAt": "..." }
}GET /reports
List your organization's reports, newest first. Optional ?limit= (1–200, default 50).
curl https://blackhorsesentinel.com/api/v1/reports?limit=20 \ -H "Authorization: Bearer $SENTINEL_API_KEY"
GET /reports/:id
Fetch a single report including the full score, drift, and signed receipt.
curl https://blackhorsesentinel.com/api/v1/reports/9c2f... \ -H "Authorization: Bearer $SENTINEL_API_KEY"
GET /usage
Check your remaining monthly quota.
curl https://blackhorsesentinel.com/api/v1/usage \ -H "Authorization: Bearer $SENTINEL_API_KEY"
Errors
Errors return JSON with an error message and a stable code.
401 unauthorized — missing/invalid/revoked key 402 quota_exceeded — monthly API quota reached (upgrade) 400 bad_request — malformed JSON 400 no_text — empty text field 413 text_too_large — text exceeds 200,000 characters 404 not_found — report id not in your org 500 internal — unexpected server error
Client SDKs
TypeScript / JavaScript
npm install @blackhorse/sentinel-sdk
import { SentinelClient } from "@blackhorse/sentinel-sdk";
const sentinel = new SentinelClient({ apiKey: process.env.SENTINEL_API_KEY! });
const report = await sentinel.analyze({
title: "FOMC statement",
sourceOutlet: "FEDERAL_RESERVE",
entity: "Federal Reserve",
text: "The Committee will continue to assess...",
});
console.log(report.tier, report.drift.driftScore);
const usage = await sentinel.usage();
console.log(usage.remaining);Python
pip install blackhorse-sentinel
from blackhorse_sentinel import SentinelClient
sentinel = SentinelClient(api_key="bhs_live_...")
report = sentinel.analyze(
title="FOMC statement",
source_outlet="FEDERAL_RESERVE",
entity="Federal Reserve",
text="The Committee will continue to assess...",
)
print(report["tier"], report["drift"]["driftScore"])
print(sentinel.usage()["remaining"])Ready to build? Choose a plan or create an API key.