A Jam for Tiger tool
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>
| Surface | Endpoint | Style | Best 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 |
"openai" (sync default)| Model | Context | Notes |
|---|---|---|
gpt-4o | 128K | Default for sync API. Strong all-rounder. |
gpt-4o-mini | 128K | Faster, cheaper. |
gpt-4.1 | 1M | Long-context tasks. |
gpt-4.1-mini | 1M | Long-context, lower cost. |
o3 | 200K | Reasoning model. temperature ignored. Use reasoningLevel. |
o3-mini | 200K | Reasoning model. temperature ignored. |
o4-mini | 200K | Reasoning model. temperature ignored. |
"gemini"| Model | Context | Notes |
|---|---|---|
gemini-2.5-flash | 1M | Default. Fast, large context. |
gemini-2.5-pro | 1M | Higher capability, slower. |
"claude"| Model | Context | Notes |
|---|---|---|
claude-opus-4-5 | 200K | Default. Most capable Claude. |
claude-sonnet-4-5 | 200K | Balanced speed and quality. |
claude-haiku-4-5 | 200K | Fastest Claude model. |
Blocks until the model responds. Returns text directly in a single HTTP call. Ideal for Google Sheets, shell one-liners, and simple scripts.
application/json| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
prompt | string | conditional | — | The prompt to send. Required unless source_run_id is provided. |
system_prompt | string | optional | — | System-level instructions prepended before the prompt. |
provider | string | optional | "openai" | Provider: "openai", "gemini", or "claude". |
model | string | optional | provider default | Model ID. Must match the chosen provider. |
temperature | number | optional | 0.3 | Sampling temperature 0–2. Ignored for o-series reasoning models. |
max_output_tokens | number | optional | 1000 | Max tokens in the response. |
web_search | boolean | optional | false | Enable web search. OpenAI: web_search_preview. Gemini: Google Search grounding. Claude: not supported. |
reasoning | string | optional | — | OpenAI o-series only: "low", "medium", or "high". |
notes | string | optional | — | Freeform notes saved with the run. |
source | string | optional | "api" | Caller label shown in history (e.g. "sheets", "pipeline"). |
source_run_id | string | optional | — | UUID of a previous run whose response is appended as [SOURCE RUN RESPONSE]. |
{
"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
}
{
"errorMessage": "Provider error detail",
"run_id": "550e8400-e29b-41d4-a716-446655440000"
}
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 -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 -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 -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"
}'
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).
application/json)| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
promptText | string | conditional | — | Prompt text. Required for JSON requests. |
provider | string | required | — | "openai", "gemini", or "claude". |
model | string | required | — | Model ID matching the chosen provider. |
temperature | number | optional | 0.3 | Sampling temperature 0–2. |
maxOutputTokens | number | optional | 2000 | Max tokens in the response. |
webSearchEnabled | boolean | optional | false | Enable web search. |
reasoningLevel | string | optional | — | OpenAI o-series: "low", "medium", "high". |
system_prompt | string | optional | — | System-level instructions. |
sourceRunId | string | optional | — | UUID of a previous run to append as context. |
multipart/form-data)Same fields as above but sent as form fields. Replace promptText with a file upload:
| Field | Type | Description |
|---|---|---|
promptFile | file | Upload 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 -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 -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"
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"
}
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
| Field | Description |
|---|---|
id | UUID of the run |
status | "completed" or "failed" |
rawResponseText | Full untruncated model response (null if failed) |
promptText | The prompt text (null when promptFile was used) |
promptFile | Filename when a file was uploaded (null otherwise) |
tokensInput | Tokens consumed by the prompt |
tokensOutput | Tokens in the response |
tokensThinking | Reasoning tokens (o-series models only, otherwise null) |
tokensTotal | Total tokens billed |
durationSecs | Wall-clock time of the LLM call in seconds |
errorMessage | Error detail when status is "failed" (null on success) |
citations | Array of web search citations (empty when off) |
createdAt | ISO timestamp |
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}]'
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
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"}'
No auth required.
curl https://promptlab.jamfortiger.com/api/healthz
# {"status":"ok"}
POST /api/run from Apps Script. =RUN_PROMPT(A2) as a custom formula.POST /api/run, get text back immediately. No polling needed..txt or .md file via multipart to POST /api/runs. No need to inline content in JSON.source_run_id (sync) or sourceRunId (async) to feed a previous run's response into the next prompt.web_search=true. citations_grouped_text gives a copy-ready formatted block.POST /api/runs, poll each for completion, compare rawResponseText and token counts.system_prompt to instruct JSON output. Claude and GPT-4o are strong at this.PATCH /api/runs/:id/notes to label runs for filtering in the UI./api/run) blocks for the full model response — typical latency 3–30s./api/runs) responds in ~100ms with status: "processing"; poll every 2s until complete.web_search_preview; Gemini uses Google Search grounding with citations; Claude does not support web search.reasoning / reasoningLevel instead.APP_PASSWORD) is separate and does not affect API access.