Documentation
From API key to first request in minutes.
AssetMeld uses an OpenAI-compatible interface, so most existing integrations only need three changes: your API key, the AssetMeld base URL and the model ID.
On this page Quickstart
Quickstart
Get your first response in three steps: create an API key, install the OpenAI SDK, and send a request.
1. Get your API key
Create an account, verify your email, and generate an API key from the dashboard. The full key is shown only once — copy it and store it securely.
2. Set your API key
export ASSETMELD_API_KEY="am_live_..."Never hard-code API keys in source code. Use environment variables or a secrets manager.
3. Send your first request
Install the OpenAI Python SDK and send a chat completion:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ASSETMELD_API_KEY"],
base_url="https://api.assetmeld.com/v1",
)
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)Other languages
curl https://api.assetmeld.com/v1/chat/completions \
-H "Authorization: Bearer $ASSETMELD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [{"role": "user", "content": "Hello!"}]
}'import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.ASSETMELD_API_KEY,
baseURL: "https://api.assetmeld.com/v1",
});
const response = await client.chat.completions.create({
model: "gpt-5.6-sol",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(response.choices[0].message.content);Authentication
All requests require a valid API key passed in the Authorization header:
Authorization: Bearer am_live_...API key lifecycle
- Create: generate from the API keys dashboard. The key secret is shown only once.
- Rotate: create a new key, update your application, then revoke the old key.
- Revoke: revocation takes effect immediately. No requests will be accepted.
If your key is compromised: revoke it immediately, create a new one, and check your usage dashboard for unexpected activity.
OpenAI Compatibility
AssetMeld implements an OpenAI-compatible API surface for supported endpoints. Compatibility does not imply that every OpenAI parameter is supported by every model.
Most applications using the OpenAI SDK can migrate by changing three things:
- API key
- Base URL →
https://api.assetmeld.com/v1 - Model ID
How parameters are handled
- Direct: fields the model accepts as-is.
- Unsupported: parameters not supported by the selected model return
400withunsupported_parameter. They are not silently ignored.
Supported endpoints
POST /v1/chat/completions— Chat CompletionsPOST /v1/responses— Responses APIPOST /v1/messages— Messages API (Anthropic SDK)
Chat Completions
POST /v1/chat/completionsRequest parameters
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Model ID from the catalog |
messages | array | Yes | Conversation messages |
temperature | number | No | Sampling temperature (0–2). Default varies by model. |
top_p | number | No | Nucleus sampling (0–1) |
max_tokens | integer | No | Maximum output tokens |
stream | boolean | No | Enable Server-Sent Events streaming (default: false) |
tools | array | No | Tool/function definitions |
tool_choice | string/object | No | Tool selection behavior (auto, none, or specific) |
response_format | object | No | Structured output (json_object or json_schema) |
stop | string/array | No | Stop sequences |
Message roles
| Role | Description |
|---|---|
system | System instructions |
user | User message |
assistant | Model response (include in multi-turn) |
tool | Tool execution result |
Response format
{
"id": "chatcmpl_xxx",
"object": "chat.completion",
"created": 1787390000,
"model": "gpt-5.6-sol",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hello!"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 6,
"total_tokens": 18
}
}finish_reason values
stop— model finished naturallylength— hit max_tokens limittool_calls— model wants to call a toolcontent_filter— output was filtered
Responses API
POST /v1/responsesThe Responses API is an OpenAI-compatible endpoint with a slightly different request shape. It supports the same models as Chat Completions.
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ASSETMELD_API_KEY"],
base_url="https://api.assetmeld.com/v1",
)
response = client.responses.create(
model="gpt-5.6-sol",
input="Explain TCP congestion control simply.",
)
print(response.output_text)curl https://api.assetmeld.com/v1/responses \
-H "Authorization: Bearer $ASSETMELD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"input": "Explain TCP congestion control simply."
}'Messages API — Anthropic SDK
POST /v1/messages/v1/messages is the native Anthropic Messages surface. Point the Anthropic (Qwen) SDK at AssetMeld and use any enabled model ID — including advanced controls such as adaptive thinking and effort levels.
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ASSETMELD_API_KEY"],
base_url="https://api.assetmeld.com/v1",
)
response = client.chat.completions.create(
model="claude-opus-5",
messages=[{"role": "user", "content": "Explain TCP congestion control simply."}],
)
print(response.choices[0].message.content)With adaptive thinking enabled, the response stream includes a dedicatedthinking block plus standard message_start,content_block_delta, and message_stop events — the same event signature as the native Messages API.
curl https://api.assetmeld.com/v1/messages \
-H "Authorization: Bearer $ASSETMELD_API_KEY" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-5",
"max_tokens": 1024,
"thinking": {"type": "adaptive", "display": "omitted"},
"messages": [{"role": "user", "content": [{"type": "text", "text": "Explain TCP congestion control simply."}]}]
}'Streaming
Enable streaming with stream=True to receive partial responses as they are generated. AssetMeld uses Server-Sent Events (SSE) compatible with the OpenAI streaming protocol.
stream = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Explain DNS simply"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta
if delta.content:
print(delta.content, end="", flush=True)Streaming behavior
- Each chunk contains a
deltawith partial content - The final chunk has
finish_reasonand empty delta - Usage is included in the final chunk when available
- If the client disconnects mid-stream, usage already generated may still be charged
Tool Calling
Tool-capable models can request that your application execute functions. AssetMeld never executes tools automatically — your application must handle the full tool-use loop.
Flow
- 1. Send request with
toolsdefinitions - 2. Model returns
tool_callsin the response - 3. Your application validates and executes the tool
- 4. Send tool result back as a
toolmessage - 5. Model generates the final answer
import os, json
from openai import OpenAI
client = OpenAI(
api_key=os.environ["ASSETMELD_API_KEY"],
base_url="https://api.assetmeld.com/v1",
)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"}
},
"required": ["city"],
},
},
}
]
# Step 1: Send request with tools
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "What is the weather in Hanoi?"}],
tools=tools,
)
message = response.choices[0].message
# Step 2: Check for tool calls
if message.tool_calls:
tool_call = message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
# Step 3: Execute the tool (your code)
weather_result = {"temperature": 31, "condition": "Cloudy"}
# Step 4: Send tool result back
messages = [
{"role": "user", "content": "What is the weather in Hanoi?"},
message,
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(weather_result),
},
]
# Step 5: Get final answer
final = client.chat.completions.create(
model="gpt-5.6-sol",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)Important notes
- Treat tool arguments as untrusted input — validate before executing
- Parallel tool calls: models may return multiple tool calls at once
- Tool support varies by model — check the model catalog for badges
Vision
Models with the Vision badge accept image inputs. Send images as URLs or base64-encoded data within the messages array.
Image URL
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image."},
{
"type": "image_url",
"image_url": {
"url": "https://example.com/photo.jpg"
},
},
],
}
],
)Base64
import base64
with open("photo.jpg", "rb") as f:
image_data = base64.standard_b64encode(f.read()).decode()
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[
{
"role": "user",
"content": [
{"type": "text", "text": "What is in this image?"},
{
"type": "image_url",
"image_url": {
"url": f"data:image/jpeg;base64,{image_data}"
},
},
],
}
],
)Vision notes
- Supported formats: JPEG, PNG, WebP
- Image tokens count toward input usage
- Check the model catalog for vision support — text-only models reject images with
400 unsupported_model_feature
Structured Outputs
Request structured JSON output with response_format:
# JSON mode
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[...],
response_format={"type": "json_object"},
)
# JSON Schema mode
response = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[...],
response_format={
"type": "json_schema",
"json_schema": {
"name": "person",
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
"required": ["name", "age"],
},
},
},
)Switching Models
The same client can call any enabled model. Change the model parameter and keep the rest of your integration:
model="gpt-5.6-sol"model="claude-opus-5"model="kimi-k3"Your application code, authentication and base URL stay the same. Browse the full catalog on the Models page.
SDK compatibility
Tested and compatible: OpenAI Python SDK, OpenAI JavaScript/TypeScript SDK, and raw HTTP (any language). Other frameworks (LangChain, LiteLLM, Vercel AI SDK) may work but are not officially tested.
Billing
AssetMeld uses prepaid billing. You are charged for tokens used on each request at the rates in effect when the request starts. Prices may change; the price active when your request begins is the price that applies.
Request lifecycle
- 1. We estimate the maximum cost upfront and hold it from your balance
- 2. Inference begins
- 3. After completion, final cost is calculated
- 4. You pay only for tokens used — the rest is returned to your balance immediately
What is charged
| Scenario | Charged? |
|---|---|
| Successful response | Yes — input + output tokens |
| Stream generates tokens, client disconnects | Partial — usage already generated |
| Invalid request (400) | No |
| Invalid API key (401) | No |
| Server error before inference | No |
| Rate limited (429) | No |
Adding balance
Top-ups are currently manual. Follow the PayPal or crypto instructions in your billing dashboard, keep your PayPal transaction ID, and contact AssetMeld on Telegram with your account email and transaction ID.
Balance updates are manual and are applied only after the payment is independently verified.
Rate Limits
Requests are subject to per-key and per-account rate limits. When a limit is exceeded, AssetMeld returns HTTP 429 with rate_limit_exceeded.
Retry strategy
| HTTP | Retry? | Action |
|---|---|---|
400 | No | Fix the request |
401 | No | Check API key |
402 | No | Add balance |
429 | Yes | Respect Retry-After, exponential backoff with jitter |
500 | Yes | Retry with backoff |
502 | Yes | Retry with backoff |
503 | Yes | Retry with backoff |
504 | Yes | Retry with backoff |
import random, time
max_retries = 5
for attempt in range(max_retries):
try:
response = client.chat.completions.create(...)
break
except Exception:
if attempt == max_retries - 1:
raise
delay = min(2 ** attempt + random.random(), 30)
time.sleep(delay)Error Handling
Every AssetMeld response includes an X-Request-ID header. Include it when contacting support.
Error response format
{
"error": {
"code": "rate_limit_exceeded",
"type": "rate_limit_error",
"message": "Rate limit exceeded. Please retry after backoff.",
"param": null
}
}Stable error codes
Use error.code for programmatic handling. The human-readable message may change.
| Code | HTTP | Meaning |
|---|---|---|
invalid_api_key | 401 | Missing, malformed, or revoked key |
invalid_request | 400 | Malformed JSON or missing required fields |
unsupported_parameter | 400 | Parameter not supported by this model |
unsupported_model_feature | 400 | Feature not supported (e.g., vision on text-only model) |
model_not_found | 400 | Model ID does not exist |
model_disabled | 400 | Model exists but is disabled |
insufficient_balance | 402 | Not enough prepaid balance |
rate_limit_exceeded | 429 | Too many requests — back off |
model_timeout | 504 | Model did not respond in time |
model_unavailable | 502 | Model returned an error |
Error examples
// 402 — Insufficient balance
{
"error": {
"code": "insufficient_balance",
"type": "billing_error",
"message": "Insufficient prepaid balance.",
"param": null
}
}// 400 — Unsupported feature
{
"error": {
"code": "unsupported_model_feature",
"type": "invalid_request_error",
"message": "Model gpt-5.6-sol does not support image input.",
"param": "messages"
}
}Models Endpoint
GET /v1/modelsReturns the list of enabled models available to your API key.
curl https://api.assetmeld.com/v1/models \
-H "Authorization: Bearer $ASSETMELD_API_KEY"{
"object": "list",
"data": [
{"id": "gpt-5.6-sol", "object": "model"},
{"id": "claude-opus-5", "object": "model"},
{"id": "kimi-k3", "object": "model"}
]
}Request IDs
Every API response includes an X-Request-ID header. Log this value and include it in support requests for fast debugging.
response = client.chat.completions.create(...)
request_id = response._request_id # or response.headers["x-request-id"]Migrate from OpenAI
What usually works unchanged
- Chat completions
- Streaming
- Tool calling
- Message format
- Python and JavaScript SDKs
What may differ
- Supported parameters (model-dependent)
- Model IDs (use AssetMeld catalog IDs)
- Rate limits
- Reasoning token billing
# Before (OpenAI)
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
# After (AssetMeld)
client = OpenAI(
api_key=os.environ["ASSETMELD_API_KEY"],
base_url="https://api.assetmeld.com/v1",
)Privacy
AssetMeld does not store your prompts or completions.
Do not send secrets, passwords, private keys, or regulated data unless your use case explicitly allows it.
Security Best Practices
- Keep API keys server-side — never expose in frontend code
- Use environment variables, not hard-coded keys
- Rotate keys periodically and after any suspected leak
- Use separate keys for development and production
- Validate tool arguments before executing them — model output is untrusted
- Set request timeouts appropriate for your use case
- Log request IDs for audit trails
- Do not log sensitive prompts
Production Best Practices
- Implement exponential backoff with jitter for retries
- Retry only retryable errors (429, 500, 502, 503, 504)
- Log request IDs, model, status, latency, and cost
- Monitor latency, failure rate, and spend
- Handle model deprecation gracefully — check the model catalog regularly
- Add application-level budget limits
- Set client-side and server-side timeouts
Parameter Compatibility
Feature availability varies by model. Check the model catalog for capability badges.
| Feature | Chat | Responses | Notes |
|---|---|---|---|
| Text input | ✅ | ✅ | |
| Streaming | ✅ | ✅ | SSE compatible |
| Tools | ✅ | ✅ | Model-dependent |
| Vision | ✅ | ✅ | Model-dependent |
| JSON output | ✅ | ✅ | Model-dependent |
| Reasoning | Partial | ✅ | Model-dependent |
| Audio | ❌ | ❌ | Not supported |
Timeouts & Concurrency
- Request timeout: requests may run for up to 600 seconds
- Streaming timeout: idle streaming connections are closed after inactivity
- Concurrent requests: limited per API key and per account
- When concurrency is exceeded, the API returns
429
Cost Calculation
Each request shows a breakdown in the usage dashboard. Here is how cost is calculated:
Input: 1,000 tokens x $2.00 / 1M = $0.002
Output: 500 tokens x $8.00 / 1M = $0.004
Total: $0.006The exact prices per model are shown on the Models page.
HTTP Headers
Request headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer am_live_... |
Content-Type | Yes | application/json |
Response headers
| Header | Description |
|---|---|
X-Request-ID | Unique request ID for support/debug |
Retry-After | Seconds to wait (on 429) |
Model IDs
- Model IDs are case-sensitive
- IDs are stable but may be deprecated with advance notice
- Always use the exact ID from the model catalog
Model lifecycle
- Active: fully supported
- Deprecated: still available but may be removed
- Unavailable: temporarily or permanently offline
Reasoning Models
Some models support extended reasoning. Reasoning tokens are billed as output tokens. Reasoning content may be exposed as reasoning_content in the response.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 | Wrong/revoked key | Check key in dashboard |
| 402 | Insufficient balance | Add balance via billing |
| 429 | Rate limit | Back off, reduce concurrency |
| 502 | Provider error | Retry with backoff |
| 504 | Timeout | Retry, shorter prompts |
Deprecation Policy
Breaking removals and model retirements are announced at least 7 days in advance when practical.
Status
Check system status at assetmeld.com/status.
Support
For account issues, billing questions, or failed requests, contact AssetMeld via Telegram (link in your dashboard). Include your account email and request ID when reporting a problem.