Quick Snippet — Invoke a Prompt with One Variable
This snippet shows the minimal, production-ready code to call a managed prompt from your client or backend, passing one dynamic variable through.
Assume the prompt welcome-email is already defined in your odnoga prompt registry with the template:
Hello {{user_name}},
Welcome to our platform!
Node.js (OpenAI SDK)
import OpenAI from 'openai';
async function sendWelcomeEmail(userName: string, userId: string) {
const client = new OpenAI({
apiKey: process.env.AIROUTER_API_KEY,
baseURL: process.env.AIROUTER_BASE_URL,
});
const response = await client.chat.completions.create({
model: 'gpt-4o-mini',
prompt: {
slug: 'welcome-email',
label: 'production',
variables: {
user_name: userName,
},
},
max_tokens: 1024,
}, {
headers: {
'x-airouter-end-user': userId,
},
});
return {
message: response.choices[0].message.content,
cost: response.headers['x-airouter-cost-usd'],
requestId: response.headers['x-airouter-request-id'],
};
}
// Usage
const result = await sendWelcomeEmail('Alice', 'user_12345');
console.log(result.message);
Python (OpenAI SDK)
import os
from openai import OpenAI
def send_welcome_email(user_name: str, user_id: str):
client = OpenAI(
api_key=os.getenv('AIROUTER_API_KEY'),
base_url=os.getenv('AIROUTER_BASE_URL'),
)
response = client.chat.completions.create(
model='gpt-4o-mini',
prompt={
'slug': 'welcome-email',
'label': 'production',
'variables': {
'user_name': user_name,
},
},
max_tokens=1024,
headers={
'x-airouter-end-user': user_id,
},
)
return {
'message': response.choices[0].message.content,
'cost': response.headers['x-airouter-cost-usd'],
'request_id': response.headers['x-airouter-request-id'],
}
# Usage
result = send_welcome_email('Alice', 'user_12345')
print(result['message'])
cURL (Direct HTTP)
#!/bin/bash
USER_NAME="Alice"
USER_ID="user_12345"
curl -X POST \
"$AIROUTER_BASE_URL/v1/chat/completions" \
-H "authorization: Bearer $AIROUTER_API_KEY" \
-H "content-type: application/json" \
-H "x-airouter-end-user: $USER_ID" \
-d '{
"model": "gpt-4o-mini",
"prompt": {
"slug": "welcome-email",
"label": "production",
"variables": {
"user_name": "'$USER_NAME'"
}
},
"max_tokens": 1024
}' | jq '.choices[0].message.content'
JavaScript (Fetch API, for Node/Edge)
async function sendWelcomeEmail(userName, userId) {
const response = await fetch(
`${process.env.AIROUTER_BASE_URL}/v1/chat/completions`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AIROUTER_API_KEY}`,
'Content-Type': 'application/json',
'x-airouter-end-user': userId,
},
body: JSON.stringify({
model: 'gpt-4o-mini',
prompt: {
slug: 'welcome-email',
label: 'production',
variables: {
user_name: userName,
},
},
max_tokens: 1024,
}),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const data = await response.json();
return {
message: data.choices[0].message.content,
cost: response.headers.get('x-airouter-cost-usd'),
requestId: response.headers.get('x-airouter-request-id'),
};
}
// Usage
const result = await sendWelcomeEmail('Alice', 'user_12345');
console.log(result.message);
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
type PromptRequest struct {
Model string `json:"model"`
Prompt struct {
Slug string `json:"slug"`
Label string `json:"label"`
Variables map[string]string `json:"variables"`
} `json:"prompt"`
MaxTokens int `json:"max_tokens"`
}
type Choice struct {
Message struct {
Content string `json:"content"`
} `json:"message"`
}
type CompletionResponse struct {
Choices []Choice `json:"choices"`
}
func SendWelcomeEmail(userName, userId string) (string, error) {
payload := PromptRequest{
Model: "gpt-4o-mini",
MaxTokens: 1024,
}
payload.Prompt.Slug = "welcome-email"
payload.Prompt.Label = "production"
payload.Prompt.Variables = map[string]string{
"user_name": userName,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(
"POST",
os.Getenv("AIROUTER_BASE_URL")+"/v1/chat/completions",
bytes.NewBuffer(body),
)
req.Header.Set("Authorization", "Bearer "+os.Getenv("AIROUTER_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("x-airouter-end-user", userId)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
var result CompletionResponse
json.Unmarshal(respBody, &result)
return result.Choices[0].Message.Content, nil
}
func main() {
message, _ := SendWelcomeEmail("Alice", "user_12345")
fmt.Println(message)
}
Key Points
✅ Prompt slug — Must match exactly (case-sensitive).
✅ Label — Typically "production" for live prompts; use "staging" for drafts.
✅ Variables — A map/dict with key names matching {{placeholders}} in your prompt template.
✅ End-user header — Always set x-airouter-end-user for accurate usage attribution.
✅ Error handling — Check HTTP status; 400 means invalid variable, 404 means prompt not found.
Response Headers
Every successful response includes:
x-airouter-request-id: 8b1a… # Unique request ID
x-airouter-cost-usd: 0.000043 # Cost of this request
x-airouter-latency-ms: 612 # Upstream latency
x-airouter-cache: miss|hit|off # Cache status
x-ratelimit-remaining-usd: 49.9999 # Budget remaining
Log these for observability and cost tracking.
Errors
| Status | Code | Reason |
|---|---|---|
400 | invalid_prompt | Required variable missing |
400 | variable_too_large | Variable over its cap (8 KB default; the prompt's declaration can raise it with max_bytes, up to 256 KB) |
404 | prompt_not_found | Slug doesn't exist in your workspace |
402 | budget_exhausted | Budget limit reached |
See Also
- Using your own data in prompts — full details on variable syntax, RAG patterns.
- Prompts and A/B — label/version resolution, experiments.
- SDK Cookbooks — more language examples.