Gen3 Gt Api Example Curl Commands - GT-Edge-AI/GT-AI-OS GitHub Wiki

Start Here

Use these copy-paste curl examples to smoke-test GT API routes. Start with discovery (GET /v1/models, GET /v1/upload-targets), run the golden-path sequence when you need conversation continuity and uploads, then poll GET /v1/files/{id} (alias GET /v1/uploads/{id}) until status is ready or failed.

Why this matters

GT API mirrors OpenAI-shaped paths under /api/tenant/v1/* but uses separate key purposes (inference, upload, conversation), conversation headers, dataset uploads, and asynchronous file processing.

Details

OpenAPI source of truth: gt-ai-os/docs/reference/GT3-TENANT-EXTERNAL-API-OPENAPI.yaml.

Key purposes (use the matching bearer secret per route)

Route family Typical key purpose Placeholder
Stateless chat, embeddings, audio, images Inference <YOUR_INFERENCE_API_KEY>
Conversation create, follow-up chat, conversation uploads Conversation <YOUR_CONVERSATION_API_KEY>
Dataset uploads, upload-target discovery, file status (upload key) Upload <YOUR_UPLOAD_API_KEY>

Issue keys from GT API → API Keys using the presets that match your integration. Allowlist published inference and dataset names before testing.

Golden-path smoke test (sequential)

Run these steps in one shell session when validating inference, persisted conversation continuity, both upload paths, and file polling. Replace every placeholder first.

# 0) Optional: create local sample upload files if missing
DEMO_DIR="$HOME/gt-api-demo-uploads"
mkdir -p "$DEMO_DIR"
[ -f "$DEMO_DIR/sample-conversation-upload.txt" ] || printf "%s\n" "Sample conversation upload file." > "$DEMO_DIR/sample-conversation-upload.txt"
[ -f "$DEMO_DIR/sample-dataset-upload.txt" ] || printf "%s\n" "Sample dataset upload file." > "$DEMO_DIR/sample-dataset-upload.txt"

# 1) Discover published model aliases
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  "https://<tenant-host>/api/tenant/v1/models" | jq .

# 2) Stateless chat (inference key)
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/chat/completions" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "messages": [{ "role": "user", "content": "Reply with exactly: Stateless API demo ok." }]
  }' | jq .

# 3) Create conversation and send first message (conversation key)
CONV_ID="$(curl -sS -i \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/conversations" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "title": "Sequential API demo"
  }' | tee /tmp/gt-conversation-create.out | awk -F': ' 'tolower($1)=="x-gt-conversation-id"{gsub("\r","",$2); print $2}')
curl -sS \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "X-GT-Conversation-Id: $CONV_ID" \
  "https://<tenant-host>/api/tenant/v1/chat/completions" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "messages": [{ "role": "user", "content": "Remember the codeword: pineapple." }]
  }' | jq .

# 4) Follow-up message in the same conversation
curl -sS \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "X-GT-Conversation-Id: $CONV_ID" \
  "https://<tenant-host>/api/tenant/v1/chat/completions" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "messages": [{ "role": "user", "content": "What codeword did I ask you to remember?" }]
  }' | jq .

# 5) Conversation-scoped upload
curl -sS -i \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "X-GT-Conversation-Id: $CONV_ID" \
  -F "file=@$HOME/gt-api-demo-uploads/sample-conversation-upload.txt;type=text/plain;filename=sample-conversation-upload.txt" \
  "https://<tenant-host>/api/tenant/v1/conversations/files"

# 6) Dataset upload (upload key)
curl -sS -i \
  -H "Authorization: Bearer <YOUR_UPLOAD_API_KEY>" \
  -F "file=@$HOME/gt-api-demo-uploads/sample-dataset-upload.txt;type=text/plain;filename=sample-dataset-upload.txt" \
  "https://<tenant-host>/api/tenant/v1/datasets/<DATASET_PUBLIC_ALIAS>/files"

# 7) Poll file status (replace <FILE_ID> with id from step 5 or 6)
curl -sS \
  -H "Authorization: Bearer <YOUR_UPLOAD_API_KEY>" \
  "https://<tenant-host>/api/tenant/v1/files/<FILE_ID>" | jq .

Per-route examples

Bearer authentication

AUTH Authorization: Bearer gtak_...

Every GT API route stays private behind tenant-local bearer-key authentication.

Key: Use the key purpose that matches the route (inference, upload, or conversation).

Prerequisites

  • Issue a GT API key from the tenant GT API workspace with the scopes and allowlists required for the route you are testing.

Replace in this example

  • <YOUR_INFERENCE_API_KEY>, <YOUR_CONVERSATION_API_KEY>, or <YOUR_UPLOAD_API_KEY> — bearer secret for the matching key purpose.
  • https://<tenant-host>/api/tenant — tenant origin plus the GT API proxy prefix.

Expected outcome

  • Requests without a valid bearer token return 401.

Notes

  • Keys are shown in plaintext once and then stored only as hashes.
  • What a caller can see depends on the key scopes, allowlists, and any linked conversation binding.
  • Inference keys may attach prompt guardrail modules and additional prompt text; GT applies those layers server-side together with the configured agent (or raw-model routing policy) for allowed calls.
Authorization: Bearer <YOUR_GT_API_KEY>
Content-Type: application/json

List published models

GET /v1/models

Returns only the published inference aliases the presented key is allowed to discover.

Key: Inference key with inference:chat (and other inference scopes as needed).

Prerequisites

  • Publish at least one inference target in GT API → Published Endpoints.
  • Allowlist that published name on the inference key you will use for chat or other inference routes.

Replace in this example

  • <YOUR_INFERENCE_API_KEY> — inference key that may discover models.
  • Pick a returned id value for <PUBLISHED_MODEL_ALIAS> in later chat or modality examples.

Expected outcome

  • HTTP 200 with a JSON list whose data[].id entries are the published names this key may use in model.

Notes

  • Each entry is a published inference name callers put in model, not a bearer secret.
  • The list can include agent-backed aliases and operator-published raw-model catalog names when the key includes inference:chat; both are filtered by the presenting key’s allowlists before they appear.
  • Raw-model catalog names appear for stateless chat discovery only; they do not unlock embeddings, audio, or image routes.
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  "https://<tenant-host>/api/tenant/v1/models"

List upload targets

GET /v1/upload-targets

Returns dataset aliases and conversation-upload targets the presented key may write to.

Key: Upload key (datasets:write) or conversation key that inherits upload access.

Prerequisites

  • Create or identify the dataset targets you want external upload keys to reach.
  • Issue an upload key (or conversation key with linked upload access) allowlisted to those targets.

Replace in this example

  • <YOUR_UPLOAD_API_KEY> or <YOUR_CONVERSATION_API_KEY> — key that may discover upload targets.
  • Pick a dataset publicAlias for <DATASET_PUBLIC_ALIAS> in dataset upload examples.

Expected outcome

  • HTTP 200 with upload targets filtered to the presenting key.
  • Conversation upload targets may note that X-GT-Conversation-Id is required at request time.

Notes

  • Use this before guessing dataset alias path segments in /v1/datasets/{alias}/files.
  • Conversation-facing keys may expose conversation-upload targets after least-privilege binding to linked upload keys.
curl -sS \
  -H "Authorization: Bearer <YOUR_UPLOAD_API_KEY>" \
  "https://<tenant-host>/api/tenant/v1/upload-targets"

Create embeddings

POST /v1/embeddings

Runs an OpenAI-compatible embeddings request using a published agent alias while GT resolves the tenant embedding model behind the trust boundary.

Key: Inference key with inference:embed for the allowlisted alias.

Prerequisites

  • Publish an agent alias the key may use for embeddings.
  • Grant inference:embed on the inference key and allowlist the alias.

Replace in this example

  • <YOUR_INFERENCE_API_KEY> — embed-scoped inference key.
  • <PUBLISHED_MODEL_ALIAS> — published agent alias from GET /v1/models (raw-model catalog names are not valid here).

Expected outcome

  • HTTP 200 with an OpenAI-shaped embeddings payload (data[].embedding).

Notes

  • The presented key must include inference:embed for the allowlisted name.
  • GT resolves vectors through the tenant trust boundary; callers still pass a published agent alias in model.
  • Use encoding_format: "float" or encoding_format: "base64" depending on what the client library expects.
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/embeddings" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "input": ["Sample text for embedding"]
  }'

Run a chat completion

POST /v1/chat/completions

Runs an OpenAI-compatible chat request using a published model alias.

Key: Inference key with inference:chat (stateless) or conversation key when using X-GT-Conversation-Id.

Prerequisites

  • Discover an allowed published name with GET /v1/models.
  • For stateless chat, use an inference key with inference:chat and no conversation header.

Replace in this example

  • <YOUR_INFERENCE_API_KEY> — inference key for stateless chat (or <YOUR_CONVERSATION_API_KEY> when a conversation header is present).
  • <PUBLISHED_MODEL_ALIAS> — published name from GET /v1/models.

Expected outcome

  • HTTP 200 with choices[0].message.content containing the assistant reply.

Notes

  • Send the user content you want the model to answer; for agent aliases, the configured agent supplies its base prompt, and the key may add prompt modules or extra prompt text on top.
  • model must be a published name this key may use: an agent alias or a published raw-model catalog name (raw-model aliases are stateless chat only).
  • Without X-GT-Conversation-Id, chat completions stay stateless and do not create a persisted GT conversation.
  • Clients that need GT-managed continuity should call POST /v1/conversations first, then reuse the returned X-GT-Conversation-Id header on follow-up chat and upload requests.
  • Conversation-facing keys may inherit their runtime allowlists from linked inference and upload keys.
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/chat/completions" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "messages": [
      { "role": "user", "content": "Reply with a one-sentence summary of the request." }
    ]
  }'

Transcribe audio

POST /v1/audio/transcriptions

Runs OpenAI-compatible speech-to-text using the published agent alias and that agent's configured STT model.

Key: Inference key with inference:transcribe for the allowlisted alias.

Prerequisites

  • Publish an agent alias with speech-to-text settings that match your tenant policy.
  • Grant inference:transcribe on the inference key.

Replace in this example

  • <YOUR_INFERENCE_API_KEY> — inference key with transcribe scope.
  • <PUBLISHED_MODEL_ALIAS> — published agent alias from GET /v1/models.
  • <LOCAL_FILE_PATH> — local audio file path (for example a .wav file that exists on disk).

Expected outcome

  • HTTP 200 with transcript text in the OpenAI-compatible response body.

Notes

  • The presented key must include inference:transcribe for the allowlisted alias.
  • The public model stays an exposed agent alias; GT resolves the underlying STT model behind the tenant trust boundary.
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  -F "model=<PUBLISHED_MODEL_ALIAS>" \
  -F "file=@<LOCAL_FILE_PATH>" \
  "https://<tenant-host>/api/tenant/v1/audio/transcriptions"

Generate speech

POST /v1/audio/speech

Runs OpenAI-compatible text-to-speech using the published agent alias and that agent's configured TTS model.

Key: Inference key with inference:speech for the allowlisted alias.

Prerequisites

  • Publish an agent alias with text-to-speech settings that match your tenant policy.
  • Grant inference:speech on the inference key.

Replace in this example

  • <YOUR_INFERENCE_API_KEY> — inference key with speech scope.
  • <PUBLISHED_MODEL_ALIAS> — published agent alias from GET /v1/models.

Expected outcome

  • HTTP 200 returning synthesized audio bytes (commonly written to a local file with curl -o).

Notes

  • The presented key must include inference:speech for the allowlisted alias.
  • Agent speech settings can supply the default voice and output format when the request omits them.
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/audio/speech" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "input": "Read the summary aloud."
  }'

Generate an image

POST /v1/images/generations

Runs OpenAI-compatible image generation using the published agent alias and that agent's configured image model.

Key: Inference key with inference:image for the allowlisted alias.

Prerequisites

  • Publish an image-capable agent alias.
  • Grant inference:image on the inference key.

Replace in this example

  • <YOUR_INFERENCE_API_KEY> — inference key with image scope.
  • <PUBLISHED_MODEL_ALIAS> — published agent alias from GET /v1/models.

Expected outcome

  • HTTP 200 with generated image payload fields in the OpenAI-compatible response.

Notes

  • The presented key must include inference:image for the allowlisted alias.
  • Dataset vision_model is unrelated here; it remains an ingestion/indexing setting, not a runtime generation selector.
curl -sS \
  -H "Authorization: Bearer <YOUR_INFERENCE_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/images/generations" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "prompt": "Generate a simple diagram for the scenario."
  }'

Create a GT conversation

POST /v1/conversations

Creates a GT-managed conversation id for clients that want persisted chat continuity and conversation-scoped uploads.

Key: Conversation key (often linked to reusable inference and upload keys).

Prerequisites

  • Issue a conversation-purpose key (or use the conversation preset) with linked inference access.
  • Discover an allowed published model name with GET /v1/models using the linked inference key or the conversation key’s inherited allowlists.

Replace in this example

  • <YOUR_CONVERSATION_API_KEY> — conversation key.
  • <PUBLISHED_MODEL_ALIAS> — published inference name the conversation may use.

Expected outcome

  • HTTP 201 (or 200 per deployment) with response header X-GT-Conversation-Id set to the persisted conversation id.
  • Save that header value as <GT_CONVERSATION_ID> for follow-up chat and conversation uploads.

Notes

  • This is a GT-specific extension; ordinary OpenAI-compatible clients can stay on stateless /v1/chat/completions.
  • model must be a published inference name that the presented key is allowed to use (agent alias or raw-model catalog name).
  • Use curl -i (or -D -) so response headers are visible; the conversation id is returned as X-GT-Conversation-Id, not only in the JSON body.
CONV_ID="$(curl -sS -i \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/conversations" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "title": "External API test thread"
  }' | awk -F': ' 'tolower($1)=="x-gt-conversation-id"{gsub("\r","",$2); print $2}')
echo "CONV_ID=$CONV_ID"

Upload into a dataset target

POST /v1/datasets/{alias}/files

Accepts multipart file uploads for a static dataset target allowed by the presented upload key.

Key: Upload key with datasets:write allowlisted to the dataset alias.

Prerequisites

  • Discover an allowed dataset alias with GET /v1/upload-targets.
  • Prepare a local file path that exists on the machine running curl.

Replace in this example

  • <YOUR_UPLOAD_API_KEY> — upload key with dataset write access.
  • <DATASET_PUBLIC_ALIAS> — dataset public alias from GET /v1/upload-targets.
  • <LOCAL_FILE_PATH> — local file path. On macOS, prefer a literal path such as $HOME/.../sample-upload.txt inside the -F argument instead of a shell variable inside -F.

Expected outcome

  • HTTP 201 with JSON containing file id — save it as <FILE_ID> for status polling.
  • Initial status / processing_status is commonly pending or processing.

Notes

  • Use this for direct dataset ingestion flows.
  • The key must carry datasets:write and be allowed to reach that dataset target.
  • The {alias} path segment is the published dataset alias, not an internal database id.
curl -sS -i \
  -H "Authorization: Bearer <YOUR_UPLOAD_API_KEY>" \
  -F "file=@<LOCAL_FILE_PATH>;type=text/plain;filename=sample-upload.txt" \
  "https://<tenant-host>/api/tenant/v1/datasets/<DATASET_PUBLIC_ALIAS>/files"

Upload into a conversation flow

POST /v1/conversations/files

Accepts multipart file uploads that auto-create and attach a conversation-scoped dataset rather than targeting a fixed dataset alias.

Key: Conversation key (or key with conversation-scoped upload permission).

Prerequisites

  • Create a conversation first with POST /v1/conversations and capture X-GT-Conversation-Id.
  • Prepare a local file path that exists on the machine running curl.

Replace in this example

  • <YOUR_CONVERSATION_API_KEY> — conversation key used for the active thread.
  • <GT_CONVERSATION_ID> — value from the X-GT-Conversation-Id response header.
  • <LOCAL_FILE_PATH> — local file path.

Expected outcome

  • HTTP 201 with JSON file id and echo of conversationId.
  • Poll GET /v1/files/{id} until processing completes when downstream RAG depends on the upload.

Notes

  • Requires X-GT-Conversation-Id.
  • The key must allow conversation-scoped uploads, either directly or through a linked upload key.
  • The upload creates or reuses the conversation upload dataset that stays attached to the active chat scope.
curl -sS -i \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "X-GT-Conversation-Id: <GT_CONVERSATION_ID>" \
  -F "file=@<LOCAL_FILE_PATH>;type=text/plain;filename=sample-upload.txt" \
  "https://<tenant-host>/api/tenant/v1/conversations/files"

Poll file processing status

GET /v1/files/{fileId}

Returns asynchronous processing state for a previously uploaded file.

Key: Same upload or conversation key that performed the upload (must be allowed to read the file).

Prerequisites

  • Complete a dataset or conversation upload and copy the returned file id.

Replace in this example

  • <YOUR_UPLOAD_API_KEY> or <YOUR_CONVERSATION_API_KEY> — key that created the upload.
  • <FILE_ID> — file id from the upload response JSON.

Expected outcome

  • HTTP 200 while processing advances through stages such as queued, processing, then ready or failed.
  • Alias route: GET /v1/uploads/{id} returns the same status envelope.

Notes

  • Use this after either dataset or conversation uploads when downstream processing is asynchronous.
  • Stop polling when status is ready (success) or failed (inspect failureReason).
curl -sS \
  -H "Authorization: Bearer <YOUR_UPLOAD_API_KEY>" \
  "https://<tenant-host>/api/tenant/v1/files/<FILE_ID>"

Conversation continuity header

HEADER X-GT-Conversation-Id

Carries the GT conversation id that ties follow-up chat turns and conversation-scoped uploads together.

Key: Conversation key on chat and upload routes that participate in the same thread.

Prerequisites

  • Run POST /v1/conversations first and capture X-GT-Conversation-Id.
  • Keep /tmp/gt-conversation-create.out or export CONV_ID in the same shell session while testing.

Replace in this example

  • <YOUR_CONVERSATION_API_KEY> — conversation key.
  • <GT_CONVERSATION_ID> — persisted conversation id from the create response header.
  • <PUBLISHED_MODEL_ALIAS> — same published model used when the conversation was created.

Expected outcome

  • Follow-up POST /v1/chat/completions responses reflect prior turns in the persisted conversation.
  • Conversation uploads accept the same header value.

Notes

  • Required for /v1/conversations/files.
  • Optional on /v1/chat/completions; when present, GT API uses the existing persisted conversation instead of stateless request history only.
  • Returned by POST /v1/conversations so clients can opt into persisted chat continuity explicitly.
curl -sS \
  -H "Authorization: Bearer <YOUR_CONVERSATION_API_KEY>" \
  -H "X-GT-Conversation-Id: <GT_CONVERSATION_ID>" \
  -H "Content-Type: application/json" \
  "https://<tenant-host>/api/tenant/v1/chat/completions" \
  -d '{
    "model": "<PUBLISHED_MODEL_ALIAS>",
    "messages": [
      { "role": "user", "content": "Continue in the same conversation context." }
    ]
  }'
⚠️ **GitHub.com Fallback** ⚠️