Quickstart
Ask Azta one question over the API and read the answer with its sources, in curl, Python or TypeScript.
Ask one question, wait for the answer, and read the provisions it cites. The samples below do exactly that.
Note: Sandbox keys come from the developer console, which opens with the API launch.
1. Get a key
Get a free sandbox key at https://console.azta.ai. A sandbox key costs nothing and never reaches the engine.
Put it in your environment. The samples read it from AZTA_API_KEY and never contain a key:
export AZTA_API_KEY=your-key-hereTo point the samples at another base URL, set AZTA_BASE_URL. It defaults to https://api.azta.ai/v1.
2. Run it
The curl sample needs curl and jq. The Python sample needs Python 3.12 and pip install httpx. The TypeScript sample needs Node 24 or later, which runs it as is.
#!/usr/bin/env bash
# Ask Azta one question, wait for the answer, print it with its sources.
# Needs curl, jq and uuidgen (or a kernel with /proc/sys/kernel/random/uuid).
set -euo pipefail
: "${AZTA_API_KEY:?Set AZTA_API_KEY to your Azta API key}"
BASE_URL="${AZTA_BASE_URL:-https://api.azta.ai/v1}"
QUESTION='Mikor alkalmazandó a fordított adózás építőipari szolgáltatásnál?'
headers="$(mktemp)"
body="$(mktemp)"
trap 'rm -f "$headers" "$body"' EXIT
# One key per question. A retry that reuses it is the same request, so it is
# charged once. A retry without it would be a new request, charged again.
IDEMPOTENCY_KEY="$(cat /proc/sys/kernel/random/uuid 2>/dev/null || uuidgen)"
IDEMPOTENCY_KEY="$(printf '%s' "$IDEMPOTENCY_KEY" | tr 'A-Z' 'a-z')"
# call METHOD URL [JSON_BODY] sets $status and leaves the reply in $body.
call() {
local args=(-sS -X "$1" "$2" -H "Authorization: Bearer $AZTA_API_KEY"
-D "$headers" -o "$body" -w '%{http_code}')
if [ -n "${3:-}" ]; then
args+=(-H 'Content-Type: application/json'
-H "Idempotency-Key: $IDEMPOTENCY_KEY" -d "$3")
fi
status="$(curl "${args[@]}")"
}
# retry_after DEFAULT prints the Retry-After seconds, else DEFAULT.
retry_after() {
local value
value="$(awk -F': *' 'tolower($1) == "retry-after" { gsub(/\r/, "", $2); print $2 }' "$headers" | tail -n 1)"
if [[ "$value" =~ ^[0-9]+$ ]]; then
echo "$value"
return
fi
echo "$1"
}
fail() {
echo "Error: $(jq -r '.error.code // "unknown"' "$body")" >&2
exit 1
}
payload="$(jq -n --arg input "$QUESTION" \
'{model: "azta-agent", input: $input, background: true, depth: "standard"}')"
# Create the response: retry 429, 500 and 503 up to 3 attempts, same key.
attempt=1
while true; do
call POST "$BASE_URL/responses" "$payload"
if [ "$status" = 200 ] || [ "$status" = 202 ]; then
break
fi
case "$status" in
429 | 500 | 503)
if [ "$attempt" -ge 3 ]; then
fail
fi
sleep "$(retry_after 1)"
attempt=$((attempt + 1))
;;
*) fail ;;
esac
done
id="$(jq -r '.id' "$body")"
# Poll every 5 seconds until the response ends; Retry-After wins on 429 and 503.
while true; do
call GET "$BASE_URL/responses/$id"
case "$status" in
429 | 503)
sleep "$(retry_after 5)"
continue
;;
200) ;;
*) fail ;;
esac
state="$(jq -r '.status' "$body")"
case "$state" in
completed) break ;;
failed | cancelled)
echo "Error: $(jq -r '.error.code // .status' "$body")" >&2
exit 1
;;
esac
sleep 5
done
jq -r '[.output[].content[] | select(.type == "output_text") | .text] | join("")' "$body"
echo
echo 'Sources:'
jq -r '.sources[] | "[\(.number)] \(.title) \(.url)"' "$body"Run bash quickstart.sh, python quickstart.py or node quickstart.ts.
3. Read the sources
The output is the answer text, a blank line, Sources:, then one line per source:
Sources:
[1] <title> <url>The number in [n] is the source_number on the answer's citations, so every answer links to the provisions it cites. See Sources for the full record.
What the samples do
Each sample sends the question with background: true, which answers 202 with the response in queued. It then polls GET /v1/responses/{id} every 5 seconds until the status is completed, failed or cancelled. On failed or cancelled it exits non-zero with the error code. See Responses.
Retries and the Idempotency-Key
Every sample makes one Idempotency-Key per question and sends it on the create request. A retry without Idempotency-Key is a new request and is charged again.
If the create fails with 429, 500 or 503, the sample waits the Retry-After seconds (1 second when the header is missing) and sends the request again with the same Idempotency-Key, at most 3 attempts. The key makes the retry the same request, so it is charged once. The samples never retry a 400, 401, 402 or 403, because a repeat would fail the same way.
While polling, a 429 or 503 waits Retry-After before the next poll.
See Errors for every code.