API Reference

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.

01

Endpoints

  • POST /api/v1/score-prompt (scope score_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 (scope brief). Generates a board-ready seven-section Decision Brief as structured JSON, with a confidence score, prompt-quality score, cited sources, and a human_escalation_hint when the question needs hands-on advisory. Set public: true to 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 ?offset pagination. Each row carries brief_id, created_at, endpoint, product, model_version, a prompt_hash fingerprint (never the raw question), and a billable flag.

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.

02

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.

03

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.

04

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
}
05

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.

06

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
}
07

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-prompt call — 25 free per calendar month.
  • $25 per standard brief call — 1 free per calendar month.
  • $99 per Deep Research brief call — 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 Required with 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.

08

Status & versioning

  • Live today: score-prompt, brief, and audit-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.

Signed by the Heartwood team at Seven Roots Consulting.