OpenAI-Compatible API
โ ๏ธ BETA: GMTech's API is currently in beta testing. We welcome your feedback!
GMTech provides a fully OpenAI-compatible API as a drop-in replacement for OpenAI's API, with access to 15+ AI providers.
Why GMTech?
- Single API, Multiple Providers - Access OpenAI, Anthropic, Google, Meta, and more
- No Vendor Lock-in - Switch models without changing code
- Transparent Pricing - Real-time cost tracking; provider cost + a small 2% API service fee, shown in every response
- OpenAI Compatible - Use existing OpenAI SDK code unchanged
Quick Start
1. Install OpenAI SDK
pip install openai
2. Replace Base URL
from openai import OpenAI
# Instead of OpenAI...
# client = OpenAI(api_key="sk-...")
# Use GMTech
client = OpenAI(
base_url="https://app.gmtech.com/v1",
api_key="gmtech_your_api_key"
)
# Everything else works the same!
Chat Completions
Basic Chat
response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is Python?"}
]
)
print(response.choices[0].message.content)
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
model |
string | โ | Required. GMTech model key (e.g. claude-sonnet-46) |
messages |
array | โ | Required. Includes role: system, user, and assistant |
temperature |
float | 0.7 |
Sampling temperature. Ignored for reasoning models (o1, o3, etc.) |
max_tokens |
integer | Provider default | Maximum tokens to generate. Honored by all providers |
Cost in Response
Every chat completion and image generation response includes a gmtech.cost_usd field with the exact USD amount charged for that request:
{
"id": "chatcmpl-123",
"choices": [...],
"usage": { "prompt_tokens": 120, "completion_tokens": 80, "total_tokens": 200 },
"gmtech": { "cost_usd": 0.000312 }
}
For image generation:
{
"created": 1677652288,
"data": [{ "url": "https://..." }],
"gmtech": { "cost_usd": 0.04 }
}
Use Any Model
# OpenAI
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}]
)
# Anthropic Claude
response = client.chat.completions.create(
model="claude-sonnet-46",
messages=[{"role": "user", "content": "Hello!"}]
)
# Google Gemini
response = client.chat.completions.create(
model="google-gemini-25-pro",
messages=[{"role": "user", "content": "Hello!"}]
)
Image Generation
response = client.images.generate(
model="gpt-image-2", # DALL-E 3
prompt="A futuristic city with flying cars",
size="1024x1024"
)
print(response.data[0].url)
Embeddings
Generate vector embeddings for text using the OpenAI SDK or a direct HTTP call. Embeddings are useful for semantic search, RAG retrieval, and deduplication.
response = client.embeddings.create(
model="text-embedding-3-small",
input="The Methow Valley trail crew meets every Saturday"
)
vector = response.data[0].embedding # list of 1536 floats
Batch multiple texts in one call:
response = client.embeddings.create(
model="text-embedding-3-small",
input=["first document", "second document", "third document"]
)
for item in response.data:
print(item.index, len(item.embedding)) # 0 1536, 1 1536, 2 1536
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
model | string | โ | Embedding model key (see below) |
input | string or array | โ | Text or array of texts to embed |
Available Models
| Key | Dimensions | Price | Notes |
|---|---|---|---|
text-embedding-3-small | 1536 | $0.02 / 1M tokens | Fastest, lowest cost |
text-embedding-3-large | 3072 | $0.13 / 1M tokens | Highest quality |
gemini-embedding-001 | 3072 | $0.20 / 1M tokens | Google โ 8k token context, multimodal |
Response
{
"object": "list",
"data": [
{"object": "embedding", "index": 0, "embedding": [0.021, -0.113, 0.049, ...]}
],
"model": "text-embedding-3-small",
"usage": {"prompt_tokens": 8, "total_tokens": 8},
"gmtech": {"cost_usd": 0.00000016}
}
Sentiment Analysis
Analyze the emotional tone of any text block. Returns 10 sentiment dimensions scored 0โ100, powered by gpt-4o-mini structured outputs.
import requests, os
response = requests.post(
"https://app.gmtech.com/v1/sentiment",
headers={"Authorization": f"Bearer {os.environ['GMTECH_API_KEY']}"},
json={"text": "I'm really excited about this new product launch!"}
)
print(response.json()["sentiment"])
# {'Positive': 82, 'Negative': 5, 'Neutral': 13, 'Joyful': 74, 'Angry': 2, ...}
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
text |
string | โ | The text block to analyze |
Response
Returns a sentiment object with 10 dimensions โ each an integer 0โ100:
Positive, Negative, Neutral, Joyful, Angry, Sad, Surprised, Confident, Anxious, Confused
Compare: Chat Completions
Run the same prompt against multiple LLM models in a single call. Returns one choice per model. Optionally saves the result as a shareable snapshot.
import requests, os
response = requests.post(
"https://app.gmtech.com/v1/compare/completions",
headers={"Authorization": f"Bearer {os.environ['GMTECH_API_KEY']}"},
json={
"models": ["gpt-4o", "claude-sonnet-46", "google-gemini-25-pro"],
"messages": [{"role": "user", "content": "Explain quantum entanglement in one sentence."}],
"gmtech": {"create_snapshot": True, "snapshot_public": True}
}
)
data = response.json()
for choice in data["choices"]:
print(choice["model"], "โ", choice["message"]["content"])
print(data["gmtech"]["snapshot_url"]) # shareable link
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
models | array | โ | Array of LLM model keys to compare |
messages | array | โ | OpenAI-format messages array |
temperature | number | Sampling temperature (default 0.7) | |
max_tokens | integer | Max tokens per model response | |
gmtech.create_snapshot | boolean | Save results as a compare snapshot (default false) | |
gmtech.snapshot_public | boolean | Make snapshot publicly shareable (default false) |
Response
Returns choices โ one entry per model โ plus a gmtech block if a snapshot was created:
{
"object": "chat.compare.completion",
"choices": [
{
"index": 0,
"model": "gpt-4o",
"message": {"role": "assistant", "content": "..."},
"finish_reason": "stop",
"usage": {"prompt_tokens": 20, "completion_tokens": 30, "total_tokens": 50},
"gmtech": {"cost_usd": 0.000312}
}
],
"gmtech": {
"snapshot_uuid": "abc123...",
"snapshot_url": "https://app.gmtech.com/snapshots/abc123..."
}
}
Compare: Image Generation
Run the same image prompt against multiple image models in a single call. Returns one image URL per model. Optionally saves the result as a shareable snapshot.
import requests, os
response = requests.post(
"https://app.gmtech.com/v1/compare/images",
headers={"Authorization": f"Bearer {os.environ['GMTECH_API_KEY']}"},
json={
"models": ["gpt-image-1", "google-imagegen-4"],
"prompt": "A futuristic city at sunset",
"gmtech": {"create_snapshot": True, "snapshot_public": True}
}
)
data = response.json()
for choice in data["choices"]:
print(choice["model"], "โ", choice["url"])
print(data["gmtech"]["snapshot_url"]) # shareable link
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
models | array | โ | Array of image model keys to compare |
prompt | string | โ | Image generation prompt |
size | string | Image dimensions (default 1024x1024) | |
gmtech.create_snapshot | boolean | Save results as a compare snapshot (default false) | |
gmtech.snapshot_public | boolean | Make snapshot publicly shareable (default false) |
Response
{
"object": "image.compare.completion",
"choices": [
{
"index": 0,
"model": "gpt-image-1",
"url": "https://storage.googleapis.com/.../abc123.webp",
"finish_reason": "stop",
"gmtech": {"cost_usd": 0.042}
}
],
"gmtech": {
"snapshot_uuid": "abc123...",
"snapshot_url": "https://app.gmtech.com/snapshots/abc123..."
}
}
Available Models
Use any model key from the GMTech model directory as the model parameter.
Browse all models โ | LLM & embedding model keys (API) โ | Image model keys (API) โ
JavaScript/TypeScript
import OpenAI from 'openai';
const client = new OpenAI({
baseURL: 'https://app.gmtech.com/v1',
apiKey: process.env.GMTECH_API_KEY
});
const response = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: 'Hello!' }]
});
console.log(response.choices[0].message.content);
cURL
curl https://app.gmtech.com/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Api-Key gmtech_your_api_key" \
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "Hello!"}]
}'
Supported Features
| Feature | Status | Notes |
|---|---|---|
| Chat Completions | โ | Full support |
| Image Generation | โ | Multiple providers |
| Sentiment Analysis | โ | POST /v1/sentiment |
| Streaming | โ | Not supported โ always returns buffered response |
| Embeddings | โ | POST /v1/embeddings โ OpenAI-compatible |
| Function Calling | ๐ | Planned |
| Vision (image input) | โ | Send images to vision-capable models via OpenAI-style image_url content โ see below |
| Internet search | โ | Set internet_enabled: true to add live web results + citations (per-search fee) |
Models & pricing
GET /v1/models lists every active model (OpenAI-compatible) and adds a
gmtech block per model with its kind and per-unit pricing. Filter by kind with
?type=llm, ?type=ig (image), or ?type=vid (video).
models = client.models.list() # OpenAI SDK
# or: GET https://app.gmtech.com/v1/models?type=llm
{
"object": "list",
"data": [{
"id": "gpt-4o",
"object": "model",
"owned_by": "openai",
"gmtech": {
"type": "llm", # llm | ig | vid
"price_input": 0.0025, # per pricing_unit
"price_output": 0.01,
"price_flat": null, # set for per-image/per-video models
"pricing_unit": "per_1k_tokens",
"tags": ["vision", "best"]
}
}]
}
A dedicated GET /api/v1/pricing/models/ (public, no auth) returns the same
pricing data plus company/product/shortname โ handy for a pricing page or
cost estimates. Same ?type= filter. Pricing is straight-through: what we pay the provider
is what you pay.
Every generation response also reports what it cost under a gmtech block:
chat, images, and embeddings all return gmtech.cost_usd (the exact
amount debited from your balance); chat and embeddings also return OpenAI-standard usage
token counts.
Vision (image input)
Vision-capable models accept images alongside text using the standard OpenAI multimodal
content format. Pass a data: URI (base64) or a public https image URL.
Sending an image to a model that isn't vision-capable returns a 400. To see which models
support vision, filter by the vision tag on the
model status page.
import base64
from openai import OpenAI
client = OpenAI(base_url="https://app.gmtech.com/v1", api_key="YOUR_KEY")
# Option A โ a public image URL
resp = client.chat.completions.create(
model="gpt-4o", # any model tagged "vision" (gpt-4o, gemini-2.5-pro, claude-*, llama-4-*, grok-4.x, nova-*, ...)
messages=[{"role": "user", "content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
]}],
)
print(resp.choices[0].message.content)
# Option B โ inline base64 (data URI)
b64 = base64.b64encode(open("photo.jpg", "rb").read()).decode()
resp = client.chat.completions.create(
model="gemini-2.5-pro",
messages=[{"role": "user", "content": [
{"type": "text", "text": "Describe this."},
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64}"}},
]}],
)
Notes: images are billed via input tokens (larger images = more tokens; the provider
counts them). Remote image URLs must be public https (fetched with SSRF protections; redirects
and private/internal hosts are rejected). Images on the last user message are sent to the model.
Internet search
Add internet_enabled: true to run a live web search, inject the results into your prompt,
and return citations. Off by default. A per-search fee (search_cost_usd) is charged on top of
token cost; sources are returned under gmtech.sources.
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "What happened in AI this week?"}],
extra_body={"internet_enabled": True}, # default False
)
print(resp.choices[0].message.content)
print(resp.model_extra["gmtech"]["sources"]) # [{n, title, url}, ...]
Error Handling
from openai import APIError, AuthenticationError, RateLimitError
try:
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}]
)
except AuthenticationError:
print("Invalid API key")
except RateLimitError:
print("Rate limit exceeded")
except APIError as e:
print(f"API error: {e}")
Migration from OpenAI
Before (OpenAI)
from openai import OpenAI
client = OpenAI(api_key="sk-...")
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}]
)
After (GMTech)
from openai import OpenAI
client = OpenAI(
base_url="https://app.gmtech.com/v1", # Only change
api_key="gmtech_..." # Only change
)
response = client.chat.completions.create(
model="gpt-4o", # Can also use claude-sonnet-46, google-gemini-25-pro, etc.
messages=[{"role": "user", "content": "Hello"}]
)
Next Steps
- Code Examples - More examples in Python, JavaScript, cURL
- Authentication - API key management and security
- Overview - Complete API reference
Need help? Contact support or join office hours