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:

Terminal
export AZTA_API_KEY=your-key-here

To 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.

Terminal
#!/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.

On this page