Two API calls.
Nothing to set up first.
Call one: fetch the safety instructions and put them in your prompt. Call two: after the reply has been sent, send it to us to check. Most teams have a first version running in about fifteen minutes. Everything else on this page is optional, and you can add it when you need it.
1 · Get a key
From your console. Test keys (hr_test_) write only to a test system, never your live record.
2 · Add the instructions
Cache them with your prompt. They are versioned and kept up to date as usage changes, and every fetch gives you the current version.
3 · Check after sending
In the background, never in the way of the reply. Problems found and the sealed record appear in your console.
Quickstart
# 1 · Safety instructions for your system prompt
curl https://harmwise.digitalsafeguard.org/api/v1/policy/block?jurisdiction=AU \
-H "Authorization: Bearer $HARMWISE_KEY"
# → { "block": "…", "hash": "sha256:…", "session_block": "…", "referral": {…} }
# 2 · After the reply has been sent, grade it
curl https://harmwise.digitalsafeguard.org/api/v1/grade \
-H "Authorization: Bearer $HARMWISE_KEY" -H "Content-Type: application/json" \
-d '{"candidate":"<the reply>","turns":[{"role":"user","content":"<what they said>"}],
"jurisdiction":"AU","policy_hash":"sha256:…"}'Prompt caching: the instructions are exactly the same text for a given module version, so they can sit inside your cached prompt. Details for each conversation always come as a separate block (session_block), never mixed into the cached one.
Versioned, and always up to date
The safety instructions change over time. We release new versions as what people say to AI, and how they use it, changes. /v1/policy/block always returns the version currently in force, with its version numbers, its hash and an ETag.
- Stay current: revalidate with If-None-Match at least once a day (cache.max_age). A 304 means you already have the current version; a 200 brings the new one. The SDKs do this on every call, at no cost.
- Cache safely: within a version the text never changes, so it stays inside your prompt cache until a new version is released.
- Prove which version: send hash as policy_hash when you check a reply. The record shows the version that shaped it, and a reply built on an out-of-date version is recorded with the gap “Old safety instructions used”.
Playground, live
Try it: check a reply with the real rules.
Paste a message and a reply. The playground runs the framework's fixed rules, checks the referral and seals a record, using the same code as the live service. It uses a shared public key with a usage limit, and writes only to a separate Playground organisation.
Uses a public test key. It writes only to the Playground's test system, never to anyone's live record.
Check a reply to see any problems found, how good the referral was, and the sealed record it creates.
Two ways to connect
1 · You control the prompt
Put the instructions in your system prompt and check each reply after it is sent. This gives the most safety for the least work, and is the fastest way to go live.
2 · You cannot edit the prompt
If your assistant runs on a platform that does not let you change its prompt, add Harmwise Guardrail as a tool (referrals/rank) using the platform's own actions feature, and check replies from the platform's transcript export. An MCP server is in development.
Platform connectors
A connector builds Harmwise Guardrail into a platform directly, so there is no code to write. The first is being built for our pilot customer's platform. Others will follow, in order of demand, for Microsoft Copilot Studio, Genesys Cloud, Salesforce, Amazon Connect and Lex, Dialogflow CX, ServiceNow and Zendesk.
What happens if you set nothing
| Setting | If you leave it out | If you set it |
|---|---|---|
| Call site | Everything counts as one place in your product | Problems reported for each place separately |
| Profile | Safety rules only · coverage: safety_only | Task problems too, and the ability to claim a release check |
| Escalation | Your reply should offer a way to reach a person; not yet checked automatically | Checked against your own service level (in development) |
| Jurisdiction | Set on each request | Reports by region |
| Environment | Taken from the key: hr_test_ keys write to a separate test record, never your live one | Nothing; the key already does it |
| Retention | None: only signals, metadata and a fingerprint | The words behind a problem, kept for as long as you choose |
When something fails
Harmwise Guardrail cannot be reached
Use the last copy of the instructions you hold. The reply goes out as normal, and the check is sent once we are back.
The checker fails or times out
With mode: async, we retry after 30 seconds, 2 minutes and 10 minutes. After that (or straight away in fast mode) it is recorded as instrument_error. The fault is ours. It is never counted against you and never reported as a pass.
We miss a disclosure or cannot read the message
The instructions for every module you use are in your prompt anyway. A message in a language we cannot read is recorded with the gap “language not graded”.
No local services in the directory
The emergency number is given, and the referral says plainly that there is no checked local service, rather than guessing.
We never block, change or remove a reply. That is how the service is built, not a setting.
Baseline
Find out what your AI is already hearing.
Baseline checks a sample of your past conversations and writes a single HTML report: how many people raised harm, how your AI replied, every problem by rule, and the known limits of the check. It runs on a test key, so results go to your test system, not your live record, and count towards your plan's monthly checks. We keep a fingerprint of each conversation, not its text.
The report has no conversation text unless you add the most serious replies with --include-replies, and never includes what the person said. If your transcripts cannot leave your organisation, we run Baseline with you on transcripts you redact first.
# example output; one conversation per line, as
# {"messages": [...]} or {"candidate": "...", "turns": [...]}
$ HARMWISE_API_KEY=hr_test_… npx harmwise baseline ./transcripts.jsonl
2,000 conversations · 1,998 graded · 0 instrument errors · 2 not graded
─────────────────────────────────────────────
disclosures detected 43 (2.2%)
with an S0 finding 6
with an S1 finding 19
no support service offered 12
no serious finding 1975 (98.8% of graded)
Report: harmwise-baseline.htmlEnterprise identity
Your directory decides who is on the team.
People sign in with their organisation's Microsoft account. With SCIM 2.0, your staff directory adds people to the team with a role (admin, developer or auditor) and removes them when they leave, so their access ends straight away. Owners are named in the console and SCIM can never change them. An owner sets how long a sign in lasts, and anyone on the team can export the audit trail.
Tenant URL https://harmwise.digitalsafeguard.org/scim/v2, with the token an owner issues under Settings. Supported: Users (create, read, filter by userName or externalId, replace, PATCH, delete) and the discovery endpoints. Groups are not used: the role travels with the user.
API reference
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /api/v1/policy/block | The current safety instructions for your modules, versioned and kept up to date (text, hash, ETag), to cache in your prompt |
| POST | /api/v1/policy/session | Details and ranked services for this conversation, from the person's message sent in the body |
| POST | /api/v1/grade | Check a reply after it is sent; saves a sealed record and returns a signed receipt |
| GET | /api/v1/grade/jobs/{id} | A queued grade's status and, once done, its record |
| GET | /api/v1/records | Your system's sealed records, newest first, with filters and cursor paging |
| GET | /api/v1/records/{id} | One record, with its seal and signed receipt |
| POST | /api/v1/records/{id}/match | Whether your copy of a conversation is the one a record was made from |
| GET | /api/v1/records/verify | Recompute your system's hash chain against the published head |
| GET | /api/v1/records/heads | Your chain head's inclusion proof in the published daily root |
| GET | /api/v1/findings | Findings with their workflow status, filtered as in the console |
| POST | /api/v1/instances/{id}/dispute | Dispute a finding as a false positive |
| GET | /api/v1/compliance/summary | The evidence board for a period, computed from the record |
| GET | /api/v1/attestations | The signed 30-day attestation (Pro and above) |
| GET | /api/v1/modules | Module versions, block hashes, what is in force, and release gates |
| GET | /api/v1/resources | The referral directory by jurisdiction, kind and language |
| POST | /api/v1/referrals/rank | Fitness-ranked services and composed referral text |
| GET | /api/v1/health | Liveness plus a real grader round-trip |
The full contract is published as OpenAPI 3.1. Send an Idempotency-Key header on /v1/grade so a retry can never seal twice. Errors are returned as RFC 9457 problem details. Keys carry the prefixes hr_live_ and hr_test_ so that secret scanners can detect them.