Give your sales assistant or agent the same engine the studio uses. You send the business's rules and the buyer's message; you get back the reply to send and the offer it carries, checked against the rules. The SNHP engine decides the offer; a small language model only reads the buyer and writes the words; every offer is checked in code before it leaves.
Calls that run a language model — /v1/policy/compile, /v1/reply,
/v1/practice/buyer and the matching MCP tools — need an access key: header
X-SNHP-Key: <key> (or Authorization: Bearer <key>; MCP: the
access_key argument). Pilot businesses get one at snhp.dev/#pilot or
hello@snhp.dev. Templates, policy checks and receipt verification are free without a key. The server keeps
no conversations: each reply returns a state you send back with the next message. Messages go to our
model provider only to read them and draft the reply.
state.Base URL https://snhp.dev. JSON in, JSON out. Errors are 400 with a
detail message; 429 when a rate or model budget is reached.
| Endpoint | What it does |
|---|---|
GET /v1/policy/templates | Worked starting policies: used-car dealer, SaaS plan, wholesale supply (Chinese). |
POST /v1/policy/compile | {description} → {ok, policy, issues, summary}. Plain words in, rules out, with what to fix before going live. |
POST /v1/policy/check | {policy} → the same, for an edited policy. No model call. |
POST /v1/reply | {policy, message, state?, engine?, flags?} → the reply to send, the offer, what decided it, the new state, and a receipt on a deal. |
POST /v1/receipt/verify | {receipt, policy, flags?} → signature and every rule re-checked. |
POST /v1/practice/buyer | {policy, history, style?} → a simulated AI buyer's next message, to try a policy. |
curl -s https://snhp.dev/v1/reply -H 'Content-Type: application/json' -H 'X-SNHP-Key: snhp_…' -d '{
"policy": { …the policy from /v1/policy/compile… },
"message": "CarMax has one for $25,900. Can you do $25,500?",
"state": null
}'
{
"kind": "offer", // offer | deal | handoff | decline
"reply": "…",
"reply_with_offer": "…\n[Offer on the table: … — $26,995]",
"offer": { "terms": {…}, "line": "…", "price": 26995, "net": 26885, "inside_policy": true },
"menu": [ { "option": "A", "line": "…", "price": 26995 }, … ], // when the policy offers a choice
"decided_by": "bundle2|engine:bundle2", // the rule or engine that decided the move
"reading": { "intent": "ask", "package": {…}, "refuses": {…}, "facts": {…} },
"state": { … }, // send this back with the next message
"done": false
}
flags is what your records confirm about the buyer (for example {"new_customer": true}),
never what the buyer claims. engine is optional: templates carry the engine that won their domain's
pre-registered test; custom policies default to bundle2. With "meso": 3 in the policy
(the default for custom policies) a reply can offer up to three options worth the same to you but built from
different trades; the buyer's pick shows what they care about, and their next message builds on it. Set
"meso": 0 to offer one deal at a time.
Streamable HTTP at https://snhp.dev/mcp/, or locally over stdio with uvx snhp
(set SNHP_ACCESS_KEY for the model-backed tools):
| Tool | What it does |
|---|---|
compile_offer_policy | Your offer in plain words (or a template id) → negotiation rules. |
draft_negotiation_reply | The buyer's latest message → the reply to send and the checked offer; keep the returned state. |
check_offer_policy | Validate an edited policy. Free, no model call. |
verify_deal_receipt | Re-check a signed deal receipt against your policy. |
{ "mcpServers": { "snhp": { "url": "https://snhp.dev/mcp/" } } }
SNHP signs the way the Universal Commerce Protocol expects, so a UCP verifier needs nothing beyond its baseline:
keys[] of our profile at
/.well-known/ucp: ES256 (P-256, the algorithm every UCP verifier
accepts) and our Ed25519 notary key.business_authorization, a detached JWS (ES256) over the
JCS bytes of the receipt (the same shape as UCP's
merchant_authorization), plus the Ed25519 notary_sig. Both are over canonical bytes, so a
receipt that passes through a browser still verifies. POST /v1/receipt/verify re-checks both./v1/reply, /v1/policy/* and /v1/receipt/* carry
RFC 9421 signatures over "@status",
content-digest and content-type (headers Signature-Input,
Signature, Content-Digest).