score_hook
Score any hook text on 5 dimensions with rewrite tips. Free during beta.
Deterministic heuristic scorer (no LLM). Args: text (3-300), platform, topic
(optional, reproduces generate's score via the verbatim-echo penalty), tags (1-5
fleet slugs, WP-J), verbosity (full keeps per-dimension attribution), api_key,
idempotency_key (replay not re-charged). Returns {score:{...,total}, verdict,
suggestions, confidence, disclaimer, credits_charged, credits_remaining, request_id}.
Errors: unauthorized, invalid_request, insufficient_credits, rate_limited.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | 1-5 lowercase slug tags ([a-z0-9_-], <=40 chars) stamped on this call's usage event so a fleet can attribute spend per campaign. Omit for no tagging. Filter later with get_usage(tag=...) / list_hooks(tag=...). | |
| text | Yes | The hook line to score, 3-300 chars. Any text is accepted (it does not have to be one Hook Detector generated) and it is never persisted as a hook you own. | |
| topic | No | The subject this text was written FOR. Pass the SAME topic string a generate call used and this reproduces the exact score.total that generate served for the hook: the scorer's verbatim-echo penalty only fires when it is told the topic, so a hook that repeats its own subject scores up to 8 points higher without it. Omit to score the text on its own (unchanged behaviour). Two caveats on exactness: a hook flagged contains_placeholder_stat was scored with a fabricated-number penalty this cannot apply, and a total capped at the deterministic template ceiling says so in score.notes at verbosity=full. | |
| api_key | No | API key for this call. Omit to fall back to the Authorization: Bearer / X-API-Key request header (streamable-HTTP only), then the VHGENGINE_API_KEY env var (the stdio default). No key resolvable -> unauthorized. | |
| platform | No | Target platform, which selects the length/format conventions the hooks are written and scored against. Defaults to tiktok when omitted. | tiktok |
| verbosity | No | How much of the response envelope to return: minimal (identity, text, score total/source, money, honesty warnings, and any persona/shape), standard (the default, including hook receipts), full (adds per-dimension score numbers, notes, and attribution). A failing phone_test survives minimal; passing phone_test, say_it, and pattern_source are standard/full detail. Shapes the RESPONSE only, never what is generated, persisted, hashed for idempotency, or charged. | standard |
| idempotency_key | No | Caller-chosen replay key (any string, unique per intended effect). A repeat call with the SAME key returns the stored result and is NEVER charged twice; the same key with different arguments is an idempotency_conflict. Omit and every call is a fresh, separately charged operation. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| score | No | Per-dimension scores plus `total`. | |
| verdict | No | One-line read of the total. | |
| replayed | No | true when an idempotency_key replayed a stored result, so nothing was charged again. The credits_charged below is what the ORIGINAL call cost. | |
| confidence | No | How much weight to put on this score. | |
| disclaimer | No | The honest limits of the scorer. Worth surfacing to your human. | |
| request_id | No | Id of this call. Keep it: get_usage(request_id=...) itemises exactly what it charged, and it identifies the call in a support question. | |
| suggestions | No | Concrete rewrite tips. | |
| credits_charged | No | Credits this call actually cost. | |
| credits_remaining | No | Your balance AFTER this charge. | |
| replayed_at_charge | No | true when the replay was detected at the charge boundary rather than up front; either way you are billed exactly once. |