Heartwood API for agents
v1.0 · Last updated: 2026-05-26
Heartwood exposes a small, opinionated API surface for AI agents acting on a buyer's behalf. The endpoints below are live today under the /api/v1/ prefix. They share the same scoring and brief-generation core the consumer site uses, so an agent and a human get the same artifact for the same input.
Endpoints
POST /api/v1/score-prompt(scopescore_prompt). Runs the Heartwood Prompt Quality Scorer on a draft question and returns a 0–100 score, a per-dimension breakdown, the missing elements, a coaching note, and an optional rewrite for sub-70 questions.POST /api/v1/brief(scopebrief). Generates a board-ready seven-section Decision Brief as structured JSON, with a confidence score, prompt-quality score, cited sources, and ahuman_escalation_hintwhen the question needs hands-on advisory. Setpublic: trueto opt the brief into a citeable permalink at/b/{slug}.GET /api/v1/audit-log. Returns your org's per-call usage log, newest first, with?limit(default 50, max 200) and?offsetpagination. Each row carriesbrief_id,created_at,endpoint,product,model_version, aprompt_hashfingerprint (never the raw question), and abillableflag.
A machine-readable manifest of this surface lives at /.well-known/agents.json — the canonical discovery document for crawling agents. The shapes below mirror it.
Authentication
Every request carries a Bearer token in the Authorization header:
Authorization: Bearer hwk_<secret>
Keys are prefixed hwk_ followed by a base64url secret. Generate one from your Heartwood account at /account/api-keys. The full secret is shown exactly once at creation; we store only a SHA-256 hash and a short display prefix (e.g. hwk_a1b2c3d4). If you lose the secret, revoke the key and create a new one. Each key carries scopes (score_prompt, brief) and a tier that sets its rate limit. Treat the secret like a password: server-side only, never in client code, never in version control.
A missing or malformed header returns 401 with a WWW-Authenticate: Bearer header. An unknown or revoked key returns 401. A key without the required scope returns 403. If the key store is briefly unreachable you get a 503 (retryable) rather than a false rejection.
Rate limits
Limits are enforced per key on a fixed 60-second window:
- standard tier: 60 requests / minute.
- agent tier: 600 requests / minute.
Successful responses include X-RateLimit-Limit and X-RateLimit-Remaining headers. Exceeding the window returns HTTP 429 with a Retry-After header giving the seconds until the window rolls over. New keys default to the standard tier.
score-prompt
Request — question is required (10–2000 characters); context is optional and folded in as extra signal:
POST /api/v1/score-prompt
Authorization: Bearer hwk_<secret>
Content-Type: application/json
{
"question": "Should we migrate our ERP to the cloud this year?",
"context": "Optional environment / constraints string."
}Response:
{
"score": 64, // integer 0-100
"tier": "Developing", // Basic | Developing | Good | Advisor-Ready
"dimension_scores": { }, // per-dimension breakdown
"missing_elements": [ "..." ], // dimensions that need more detail
"coaching_note": "...", // one human-readable line of coaching
"rewrite": "..." // present only when score < 70
}brief
Request — question is required (10–2000 characters). The rest are optional context that sharpens the brief:
POST /api/v1/brief
Authorization: Bearer hwk_<secret>
Content-Type: application/json
{
"question": "Should we migrate our ERP to the cloud this year?",
"context": "...", // optional
"industry": "...", // optional
"revenue_band": "...", // optional
"urgency": "...", // optional
"depth": "...", // optional
"public": false // optional; true → citeable /b/{slug} permalink
}Response (seven-section Decision Brief):
{
"brief_id": "uuid",
"slug": "string",
"public": false,
"bottom_line": "...",
"your_situation": "...",
"decision_statement": "...",
"business_exposure": "...",
"the_panels_assessment": "...",
"options": [ ... ],
"recommendation": { },
"risks": [ ... ],
"thirty_sixty_ninety": [ ... ],
"confidence_score": 87, // integer 0-100
"prompt_quality_score": 78, // integer 0-100
"cited_sources": [ { "title": "...", "url": "..." } ],
"human_escalation_hint": { "flag": false, "reason": null },
"signature_block": {
"author": "...",
"methodology_version": "v1.0",
"methodology_url": "https://heartwood.sevenrootsconsulting.com/methodology",
"model": "claude-sonnet-4-20250514",
"generated_at": "2026-05-26T14:32:01Z"
},
"disclaimer": "Advisory output. The buyer signs the decision."
}The signature_block.methodology_version field pins each brief to a specific revision of the Heartwood methodology, so an audit trail can reconstruct exactly which methodology was applied at the time of generation.
audit-log
Read your org's per-call usage log. Authenticated by the same Bearer key; scoped to the key owner's org. Pagination via ?limit (default 50, max 200) and ?offset (default 0).
GET /api/v1/audit-log?limit=50&offset=0 Authorization: Bearer hwk_<secret>
Response:
{
"usage": [
{
"brief_id": "uuid | null", // null for score-prompt calls
"created_at": "2026-05-26T14:32:01Z",
"endpoint": "brief", // score_prompt | brief
"product": "brief_standard", // score_prompt | brief_standard
"model_version": "claude-sonnet-4-20250514",
"prompt_hash": "sha256-hex", // fingerprint, never the raw question
"billable": true // true once past the free monthly quota
}
],
"limit": 50,
"offset": 0
}Pricing & free quota
Pay as you go, anchored to human pricing — an agent and a human pay the same per output because the output is the same artifact. Each org (your API key's owner) gets a free monthly allowance per product; beyond it, calls are billed by Stripe metered usage.
- $0.10 per
score-promptcall — 25 free per calendar month. - $25 per standard
briefcall — 1 free per calendar month. - $99 per Deep Research
briefcall — planned, not yet available.
The free quota resets at the start of each calendar month (UTC). While you are within the free allowance, calls succeed and are not billed. Once the allowance is used up:
- If billing is enabled for your org, the call succeeds and one metered usage unit is reported to Stripe.
- If billing is not enabled, the call returns HTTP
402 Payment Requiredwith a message and a link to enable billing at /account/api-keys.
HTTP/1.1 402 Payment Required
{
"error": "Free monthly quota for 'brief_standard' reached. Enable billing at https://heartwood.sevenrootsconsulting.com/account/api-keys to continue."
}Enable per-call billing from your account dashboard. It subscribes your org to two metered prices (one per product) with no fixed fee — you are only charged for usage past the free allowance.
Status & versioning
- Live today:
score-prompt,brief, andaudit-log, all under/api/v1, plus per-call billing with a free monthly quota. - Coming next: a Deep Research brief depth ($99 per call, planned).
This page is versioned. Current revision is v1.0, last updated 2026-05-26. Material changes to the API surface bump the version and update both this page and the agents.json manifest. For early access or to coordinate an integration, write to panel@sevenrootsconsulting.com.