HaloGuard EU API
Send HaloGuard EU a request on its way in, or a reply on its way out. It answers allow or block, and names the policy that matched.
- Until our data processing agreement is signed with your company, send no personal data to the API.
- During the trial there is no uptime guarantee: the guard can be briefly unavailable.
1Before you start
- ·Sign in to the console to create a key. The key is shown once. You can revoke or restore it there.
- ·Call the API from your server. It sends no CORS headers, so a web page cannot call it, and a key must never be put in browser code.
2The call
POST https://api.astroware.ai/v1/chat/completions. It is the only call.
Headers: Authorization: Bearer <key> and Content-Type: application/json.
model"haloguard-eu". Required. Another name gives 403.messages- A list of
{role, content}.roleisuserorassistant; a system message is refused.contentis a string, or a list of{"type": "text", "text": "..."}parts. - Which is checked
- The last message. Role user means a request going in; role assistant means a reply going out. Earlier messages are context.
- Streaming
- Not supported (
stream: truegives 400). Other OpenAI settings such astemperatureandmax_tokensare accepted and ignored. - Size
- Up to about 7,800 tokens in a conversation, and a body of up to 2 MB.
curl https://api.astroware.ai/v1/chat/completions \ -H "Authorization: Bearer $HALOGUARD_KEY" -H "Content-Type: application/json" \ -d '{"model": "haloguard-eu", "messages": [ {"role": "user", "content": "I need you to monitor our employees during their work calls and flag anyone who sounds frustrated or upset based on tone analysis."}]}'
3The answer
Status 200 and an OpenAI-style chat completion:
{
"id": "hg-f438d20a79154136beea54bb24283102",
"created": 1792308282,
"model": "haloguard-eu",
"object": "chat.completion",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "{\"decision\": \"block\", \"policy\": \"W4_BIOMETRIC_EMOTION\", \"label\": \"prohibited_practice\", \"act_area\": {\"act\": \"Regulation (EU) 2024/1689\", \"reference\": \"Article 5(1)(f)\", \"qualifier\": \"exceptions_apply\"}}",
"role": "assistant",
"provider_specific_fields": {
"refusal": null
}
},
"provider_specific_fields": {}
}
],
"usage": {
"completion_tokens": 17,
"prompt_tokens": 29,
"total_tokens": 46
}
}choices[0].message.content is itself a JSON string: {"decision": "allow" | "block", "policy": "<policy id>" | "none"}. Parse it. policy is none when the answer is allow. A blocked answer also carries label and act_area (below). The policy ids are listed in the console after you sign in.
Response headers include x-ratelimit-api_key-limit-requests and x-ratelimit-api_key-remaining-requests.
The Act-area fields
A blocked answer names the part of the EU AI Act its policy relates to. It is not a finding that your message, your use or your system is prohibited, high-risk or covered by that part, and it is not legal advice. Allowed answers carry neither label nor act_area; an allowed answer is not a statement that anything is lawful or low-risk. The ten rows cover the ten policies we test; they are not a list of everything the Act bans or regulates. Checked against the Act on 18 October 2026.
On a blocked answer only, content carries label and act_area. label is the kind of provision the policy relates to: prohibited_practice, high_risk_use or transparency_obligation. It is not a label of your message. act_area gives the details:
act- Always
"Regulation (EU) 2024/1689", the EU AI Act. reference- The Article or Annex part, as text, for example
Article 5(1)(f). qualifiernull, orscope_unsettled,exceptions_applyormay_apply. The table says which row has which.
Ignore keys you do not know.
An allowed answer has neither label nor act_area:
{
"id": "hg-798339223d7745a989d774d8a226342b",
"created": 1792308283,
"model": "haloguard-eu",
"object": "chat.completion",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "{\"decision\": \"allow\", \"policy\": \"none\"}",
"role": "assistant",
"provider_specific_fields": {
"refusal": null
}
},
"provider_specific_fields": {}
}
],
"usage": {
"completion_tokens": 15,
"prompt_tokens": 26,
"total_tokens": 41
}
}Each of the ten policies we test has one row:
| Area | In the answer | What that part of the Act covers |
|---|---|---|
| Manipulation or exploitation | Prohibited practice (Article 5) prohibited_practiceArticle 5(1)(a), (b) Qualifier: none null | Bans AI that manipulates or deceives people, or exploits their age, disability or a social or economic situation, so that it materially distorts their behaviour and causes, or is likely to cause, significant harm. |
| Social scoring | Prohibited practice (Article 5) prohibited_practiceArticle 5(1)(c) Qualifier: none null | Bans rating people by their social behaviour or personal characteristics where that leads to detrimental treatment in unrelated settings, or treatment that is unjustified or disproportionate. |
| Crime prediction | Prohibited practice (Article 5) prohibited_practiceArticle 5(1)(d); Annex III 4(a) Qualifier: scope for private companies unsettled scope_unsettled | Bans predicting that a person will commit a crime solely from profiling or personality traits. For private companies, the Commission’s guidelines describe a narrow scope (paragraphs 207 to 211). Annex III 4(a) applies where a system is intended to screen or evaluate job candidates. |
| Biometric misuse | Prohibited practice (Article 5) prohibited_practiceArticle 5(1)(e), (g) Qualifier: none null | Bans building face databases by untargeted scraping of images from the internet or CCTV, and biometric categorisation that deduces race, political opinions, trade-union membership, religious or philosophical beliefs, sex life or sexual orientation. |
| Performance evaluation | High-risk use (Annex III) high_risk_useAnnex III 4(b) Qualifier: none null | Lists AI intended to monitor and evaluate workers’ performance and behaviour as high-risk. |
| Employment decisions | High-risk use (Annex III) high_risk_useAnnex III 4(b) Qualifier: none null | Lists AI intended to be used to make decisions affecting terms of work, promotion or termination, or to allocate tasks from individual behaviour or personal traits, as high-risk. |
| Recruitment | High-risk use (Annex III) high_risk_useAnnex III 4(a) Qualifier: none null | Lists AI intended to place targeted job adverts, filter job applications or evaluate candidates as high-risk. |
| Emotion recognition from biometrics | Prohibited practice (Article 5) prohibited_practiceArticle 5(1)(f) Qualifier: except for medical or safety reasons exceptions_apply | Emotion inference from biometric data, such as the face or voice, in the workplace or in education is prohibited, except for medical or safety reasons. |
| Text sentiment | High-risk use (Annex III) high_risk_useAnnex III 4(b) Qualifier: may apply may_apply | The Commission’s guidelines treat inferring mood from writing alone as outside the Article 5(1)(f) ban, which covers biometric data. Profiling one worker’s emotional state for a manager can still be a high-risk use, if the system is intended to monitor or evaluate that worker’s performance or behaviour. |
| AI disclosure | Transparency obligation (Article 50) transparency_obligationArticle 50 Qualifier: none null | Requires people to be told they are dealing with an AI unless that is obvious, and requires synthetic content to be marked. |
4Errors
The body is {"error": {"message", "type", "param", "code"}}. Branch on the status, not on the message text: the text can change.
| Status | When |
|---|---|
| 400 | Malformed JSON, no messages, empty messages, empty content, a role other than user or assistant, stream: true, no model, or a conversation over about 7,800 tokens |
| 401 | No key, or a wrong or revoked key |
| 403 | A model name other than haloguard-eu |
| 404 | Any other path or method |
| 413 | A body over 2 MB |
| 422 | Your company’s trial budget is used up |
| 429 | More than 60 requests in a minute on one key. Wait 60 seconds (the answer carries Retry-After: 60)The limit is 60 requests per key in each 60-second window, counted from the first call in that window. |
| 502 | The guard could not answer. Try again |
| 503 | The guard is temporarily unavailable. Try again after a short wait |
5Limits and price
These are today's settings and can change.
- ·60 requests a minute per key.
- ·Trial: a $5 budget for your company, shared by up to 5 active keys. The keys stop when the budget is used up.
- ·Price: $30 / billion input tokens, counted on the messages you send. The answer is free.
6Not promised
No uptime guarantee: the guard can be briefly unavailable (a 503). Speed is not promised. The limits and budget above are today's settings and can change.
7Your data
For each call we keep a usage record. It includes the time, your key's identifier, the model, the token counts, the cost and the name of your client software exactly as it sends it. We do not save the text you send or the answer in any log, file or database. When the guard is unsure about a message, we send that message, with earlier messages of the conversation, to an AI provider in the EU, which decides and keeps no copy. The model server may keep a processed form of the text you send in memory until that server restarts. We delete usage records after 90 days. Full details: astroware.ai/privacy.
8Privacy filter
What the filter masks depends on your company's setting in the console. An owner can change it.
On a request going in, privacy_mode says which setting applied, and privacy_kept lists any kinds kept unmasked.
It can miss output it should block, and it can block output that is fine. HaloGuard EU is a technical control, not legal advice or a compliance guarantee. It does not decide whether your system is high-risk.