api.shieldie.ai

A private text-generation API. Send a chat-style request, get a reply — streaming or all at once. Access is by API key issued from the admin panel.

Base URL   https://api.shieldie.ai
Endpoint   POST /v1/messages
Auth   x-api-key: sk-shd-…  (or Authorization: Bearer sk-shd-…)

Getting a key

Keys are issued from the password-protected admin panel. A key is shown once, at creation — copy it then. Present it on every request in the x-api-key header.

Request

A JSON body with a list of messages. The model field is optional — there is a single model, default, and it is used whether or not you name one.

field
messagesrequired — array of {"role":"user"|"assistant","content":"…"}
max_tokensrequired — positive integer; caps the answer (approximately, see Errors and limits)
systemoptional — a system instruction string
streamoptional — true for server-sent events
modeloptional — accepted and ignored; always default

curl

curl https://api.shieldie.ai/v1/messages \
  -H "x-api-key: $SHIELDIE_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "max_tokens": 256,
    "messages": [{"role": "user", "content": "Napisz jedno zdanie po polsku."}]
  }'

Response

{
  "id": "msg_…",
  "type": "message",
  "role": "assistant",
  "model": "default",
  "content": [{ "type": "text", "text": "…" }],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 12, "output_tokens": 34 }
}

Python

import requests

r = requests.post(
    "https://api.shieldie.ai/v1/messages",
    headers={"x-api-key": "sk-shd-...", "content-type": "application/json"},
    json={
        "max_tokens": 256,
        "messages": [{"role": "user", "content": "Hello!"}],
    },
)
print(r.json()["content"][0]["text"])

Streaming

Set "stream": true. The response is a text/event-stream with these events: message_start → content_block_start → content_block_delta (repeated, each carrying a text_delta) → content_block_stop → message_delta → message_stop, with ping keep-alives: the stream opens within a few seconds of the model starting and carries a ping at least every 15 seconds while the model works, even before the first text. A failure after the stream opened arrives as an error event.

curl -N https://api.shieldie.ai/v1/messages \
  -H "x-api-key: $SHIELDIE_API_KEY" \
  -H "content-type: application/json" \
  -d '{"max_tokens":128,"stream":true,
       "messages":[{"role":"user","content":"Count to five."}]}'

Tools (function calling)

Pass tools with your request. The model may answer with a tool_use block instead of text; your client runs the tool and sends the outcome back as a tool_result in the next request. The server never executes anything.

curl https://api.shieldie.ai/v1/messages \
  -H "x-api-key: $SHIELDIE_API_KEY" -H "content-type: application/json" \
  -d '{
    "max_tokens": 512,
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather for a city",
      "input_schema": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"]
      }
    }],
    "messages": [{ "role": "user", "content": "What is the weather in Kraków?" }]
  }'

A tool call comes back as:

{
  "stop_reason": "tool_use",
  "content": [
    { "type": "tool_use", "id": "toolu_…", "name": "get_weather", "input": { "city": "Kraków" } }
  ]
}

Run the tool, then continue the conversation with the result:

"messages": [
  { "role": "user", "content": "What is the weather in Kraków?" },
  { "role": "assistant", "content": [
      { "type": "tool_use", "id": "toolu_…", "name": "get_weather", "input": { "city": "Kraków" } } ] },
  { "role": "user", "content": [
      { "type": "tool_result", "tool_use_id": "toolu_…", "content": "18°C, sunny" } ] }
]

Use tool_choice to steer it: {"type":"auto"} (default), {"type":"any"} (must call some tool), {"type":"tool","name":"…"} (must call that one; the name must be a declared tool), or {"type":"none"} (no tool call this turn). Any other value is a 400.

Tool support is best-effort: one tool call per turn (no parallel calls), streaming responses that carry a tool call are delivered buffered rather than incrementally, and input_schema is guidance — validate the arguments on your side.

A call is recognised only when the model ends its reply with it, on a line of its own, naming one of the tools you declared. A call merely quoted in the reply (say, one that appeared in a tool result), a second call, or an undeclared name comes back as plain text with stop_reason: "end_turn". At most 64 tools per request.

Other endpoints

method / pathwhat
GET /v1/modelsList the available model (needs a key).
POST /v1/messages/count_tokensApproximate input token count (about three characters per token, tool definitions included).
GET /healthLiveness check (public).

Errors and limits

An error body looks like {"type":"error","error":{"type":"…","message":"…"}}.

status / typewhen
400 invalid_request_errorA malformed request, unsupported content (images, documents), invalid Unicode (lone surrogates), or a NUL character in the system prompt or tool definitions.
401 authentication_errorMissing, wrong, revoked or expired key.
413 request_too_largeThe system prompt plus tool definitions are too large (about 100 kB), the prompt is over your key's size cap, or it is too long for the model.
429 rate_limit_errorThe server is busy, or your key's daily limit (or budget) is reached. Always carries Retry-After in seconds: short when busy, until 00:00 UTC for a daily limit. Wait at least that long before retrying.
529 overloaded_errorThe model is temporarily overloaded. Carries Retry-After; retry after that. It does not count toward your daily limit.
502 / 504The model failed or did not answer in time; a later retry may succeed. A 502 with Retry-After means the model is unavailable for a while; it does not count toward your daily limit.

When the server is busy a request waits briefly (up to about 20 s) for a free slot before a 429 is returned.

Good to know