PromptLab API Documentation

PromptLab is a Jam for Tiger tool for running prompts through OpenAI, Gemini, and Claude models via sync and async APIs. All runs are persisted, visible in the PromptLab UI, and queryable via the API.

Base URL: https://promptlab.jamfortiger.com
All endpoints are under /api. Bearer token required on all routes except /api/healthz.
Auth header: Authorization: Bearer <API_AUTH_TOKEN>

Two API surfaces

SurfaceEndpointStyleBest for
Sync POST /api/run Blocks until complete. snake_case params. Google Sheets, simple scripts
Async POST /api/runs Returns immediately, poll for result. camelCase params. File upload supported. Pipelines, large files, automation

Providers & Models

provider: "openai" (sync default)

ModelContextNotes
gpt-4o128KDefault for sync API. Strong all-rounder.
gpt-4o-mini128KFaster, cheaper.
gpt-4.11MLong-context tasks.
gpt-4.1-mini1MLong-context, lower cost.
o3200KReasoning model. temperature ignored. Use reasoningLevel.
o3-mini200KReasoning model. temperature ignored.
o4-mini200KReasoning model. temperature ignored.

provider: "gemini"

ModelContextNotes
gemini-2.5-flash1MDefault. Fast, large context.
gemini-2.5-pro1MHigher capability, slower.

provider: "claude"

ModelContextNotes
claude-opus-4-5200KDefault. Most capable Claude.
claude-sonnet-4-5200KBalanced speed and quality.
claude-haiku-4-5200KFastest Claude model.

POST /api/run — Synchronous API

Blocks until the model responds. Returns text directly in a single HTTP call. Ideal for Google Sheets, shell one-liners, and simple scripts.

Request — application/json

ParameterTypeRequiredDefaultDescription
promptstringconditionalThe prompt to send. Required unless source_run_id is provided.
system_promptstringoptionalSystem-level instructions prepended before the prompt.
providerstringoptional"openai"Provider: "openai", "gemini", or "claude".
modelstringoptionalprovider defaultModel ID. Must match the chosen provider.
temperaturenumberoptional0.3Sampling temperature 0–2. Ignored for o-series reasoning models.
max_output_tokensnumberoptional1000Max tokens in the response.
web_searchbooleanoptionalfalseEnable web search. OpenAI: web_search_preview. Gemini: Google Search grounding. Claude: not supported.
reasoningstringoptionalOpenAI o-series only: "low", "medium", or "high".
notesstringoptionalFreeform notes saved with the run.
sourcestringoptional"api"Caller label shown in history (e.g. "sheets", "pipeline").
source_run_idstringoptionalUUID of a previous run whose response is appended as [SOURCE RUN RESPONSE].

Response 200

{
  "text": "Model response text...",
  "citations": [
    { "index": 1, "url": "https://example.com", "title": "Title", "domain": "example.com" }
  ],
  "citations_grouped_text": "example.com (1 reference)\n[1] Title\nhttps://example.com",
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "web_search_enabled": false,
  "duration_ms": 3241
}

Response 400 / 401 / 500

{
  "errorMessage": "Provider error detail",
  "run_id": "550e8400-e29b-41d4-a716-446655440000"
}

curl — minimal

curl -X POST https://promptlab.jamfortiger.com/api/run \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Summarise this in 3 bullet points."}'

curl — Claude with system prompt

curl -X POST https://promptlab.jamfortiger.com/api/run \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Review this clause for risks.",
    "system_prompt": "You are a legal analyst. Be concise.",
    "provider": "claude",
    "model": "claude-sonnet-4-5",
    "temperature": 0.2,
    "max_output_tokens": 800
  }'

curl — Gemini with web search

curl -X POST https://promptlab.jamfortiger.com/api/run \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Latest news on LLM context window sizes",
    "provider": "gemini",
    "model": "gemini-2.5-flash",
    "web_search": true
  }'

curl — chain from a previous run

curl -X POST https://promptlab.jamfortiger.com/api/run \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "Translate the above into French.",
    "source_run_id": "550e8400-e29b-41d4-a716-446655440000"
  }'

POST /api/runs — Async API

Returns immediately with status: "processing". Poll GET /api/runs/:id until status is "completed" or "failed". Supports both application/json and multipart/form-data (file upload).

Request — JSON (application/json)

ParameterTypeRequiredDefaultDescription
promptTextstringconditionalPrompt text. Required for JSON requests.
providerstringrequired"openai", "gemini", or "claude".
modelstringrequiredModel ID matching the chosen provider.
temperaturenumberoptional0.3Sampling temperature 0–2.
maxOutputTokensnumberoptional2000Max tokens in the response.
webSearchEnabledbooleanoptionalfalseEnable web search.
reasoningLevelstringoptionalOpenAI o-series: "low", "medium", "high".
system_promptstringoptionalSystem-level instructions.
sourceRunIdstringoptionalUUID of a previous run to append as context.

Request — File upload (multipart/form-data)

Same fields as above but sent as form fields. Replace promptText with a file upload:

FieldTypeDescription
promptFilefileUpload a .txt, .md, or .json file. Its content becomes the prompt. Filename is saved and returned.

When a file is uploaded: promptText is omitted from all responses. Only promptFile (the filename) is returned.

curl — JSON

curl -X POST https://promptlab.jamfortiger.com/api/runs \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "promptText": "Explain Kubernetes in plain English.",
    "provider": "openai",
    "model": "gpt-4o",
    "temperature": 0.3,
    "maxOutputTokens": 600,
    "webSearchEnabled": false
  }'

curl — file upload

curl -X POST https://promptlab.jamfortiger.com/api/runs \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -F "promptFile=@/path/to/prompt.txt" \
  -F "provider=openai" \
  -F "model=gpt-4o" \
  -F "temperature=0.3" \
  -F "maxOutputTokens=1000" \
  -F "webSearchEnabled=false"

Initial response (status: processing)

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "provider": "openai",
  "model": "gpt-4o",
  "promptFile": "prompt.txt",
  "promptText": null,
  "createdAt": "2025-05-17T00:19:00.000Z"
}

Polling pattern

RUN_ID="550e8400-e29b-41d4-a716-446655440000"
while true; do
  RESULT=$(curl -s -H "Authorization: Bearer $API_AUTH_TOKEN" \
    https://promptlab.jamfortiger.com/api/runs/$RUN_ID)
  STATUS=$(echo $RESULT | jq -r '.status')
  if [ "$STATUS" != "processing" ]; then
    echo $RESULT | jq '{status, rawResponseText, tokensTotal, durationSecs, errorMessage}'
    break
  fi
  sleep 2
done

Completed run response fields

FieldDescription
idUUID of the run
status"completed" or "failed"
rawResponseTextFull untruncated model response (null if failed)
promptTextThe prompt text (null when promptFile was used)
promptFileFilename when a file was uploaded (null otherwise)
tokensInputTokens consumed by the prompt
tokensOutputTokens in the response
tokensThinkingReasoning tokens (o-series models only, otherwise null)
tokensTotalTotal tokens billed
durationSecsWall-clock time of the LLM call in seconds
errorMessageError detail when status is "failed" (null on success)
citationsArray of web search citations (empty when off)
createdAtISO timestamp

GET /api/runs — List runs

Returns all runs ordered by newest first. Summary objects only (no rawResponseText).

curl -s -H "Authorization: Bearer $API_AUTH_TOKEN" \
  https://promptlab.jamfortiger.com/api/runs | jq '[.[] | {id, status, model, durationSecs}]'

GET /api/runs/:id — Run detail

Full run detail including rawResponseText, all token counts, citations, and errorMessage.

curl -s -H "Authorization: Bearer $API_AUTH_TOKEN" \
  https://promptlab.jamfortiger.com/api/runs/550e8400-e29b-41d4-a716-446655440000

PATCH /api/runs/:id/notes — Update notes

curl -X PATCH https://promptlab.jamfortiger.com/api/runs/550e8400-e29b-41d4-a716-446655440000/notes \
  -H "Authorization: Bearer $API_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"notes": "Good result — use for blog post"}'

GET /api/healthz — Health check

No auth required.

curl https://promptlab.jamfortiger.com/api/healthz
# {"status":"ok"}

Use cases


Notes & behaviour