Getting Started
The AI Proxy API enables seamless access to multiple AI models through one unified endpoint. Simply visit your dashboard to create an API key. Every key contains a Consumer Key and a Consumer Secret for request authentication. The Consumer Secret is never sent over the network. it is used to generate secure request signatures, ensuring maximum credential safety.
When creating an API key, you can configure optional settings such as token limits, request limits, AI model restrictions, and expiration dates.
All API keys use the same base URL. See the Signature Generation section to learn how to authenticate your requests, or use our SDKs which handles authentication automatically.
Base URL:
https://api.bitmesh.ai
Software Development Kits (SDKs)
We provide official SDKs for popular programming languages to make integration easier.
Signature Generation
All API requests must be authenticated using OAuth 0-legged (also known as "two-legged OAuth"). This method uses your consumer key and consumer secret to generate a signature for each request. No user tokens are required.
How OAuth 0-Legged Works
OAuth 0-legged authentication requires you to include OAuth details in the Authorization
header of every request. The header format is:
Authorization: OAuth oauth_consumer_key="YOUR_CONSUMER_KEY",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="TIMESTAMP",
oauth_nonce="UNIQUE_RANDOM_STRING",
oauth_version="1.0",
oauth_signature="COMPUTED_SIGNATURE"
OAuth Parameters
| Name | Description |
|---|---|
oauth_consumer_key
|
Your consumer key provided when you create an API key. Equivalent to a username. |
oauth_signature_method
|
Always HMAC-SHA1
(see RFC 5849
Section 3.4.2).
|
oauth_timestamp
|
Timestamp when the request was generated. Timestamp is valid for 5 minutes. |
oauth_nonce
|
Uniquely generated random string. Recommended length 32 characters. Same value cannot be used more than once. |
oauth_version
|
Always 1.0.
|
oauth_signature
|
String made up of Request Method, normalized URL, and normalized parameters joined together, which is then encrypted using HMAC-SHA1 against your Consumer Secret. The request body is not included in the signature string. |
Signature Generation Process
To generate the OAuth signature, follow these steps:
- Normalize the URL: Parse the request URL and build a normalized version (scheme://host:port/path). Include port only if it's non-standard (not 80 for HTTP, not 443 for HTTPS).
- Collect parameters: Gather all OAuth parameters (consumer key, timestamp, nonce, version, signature method) and any query parameters from the URL. Exclude the oauth_signature parameter itself.
- Normalize parameters: Sort all parameters alphabetically by key,
then URL-encode each key and value, joining them with
=and separating pairs with&. - Build signature base string: Create a string in the format
METHOD&URL&PARAMSwhere METHOD is the HTTP method (e.g., POST), URL is the normalized URL, and PARAMS is the normalized parameter string. URL-encode each component. - Generate signature: Create a signing key by URL-encoding your
consumer secret and appending
&(since we don't use tokens). Then compute the HMAC-SHA1 hash of the signature base string using the signing key, and base64-encode the result.
Required Headers
Every API request must include the following headers:
Authorization: OAuth 1.0 authorization header with all OAuth parameters and signatureContent-Type:application/jsonX-Payload-Signature: SHA256 hash of the JSON request body concatenated with your consumer key and the OAuth signature
Code Implementation
Here are the PHP functions to implement the signature generation process:
function generateOAuthParams(string $method, string $url, string $consumerKey, string $consumerSecret): array
{
$params = [
'oauth_consumer_key' => $consumerKey,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => (string) time(),
'oauth_nonce' => bin2hex(random_bytes(8)),
'oauth_version' => '1.0',
];
$params['oauth_signature'] = generateSignature($method, $url, $params, $consumerSecret);
return $params;
}
function generateSignature(string $method, string $url, array $params, string $consumerSecret): string
{
// Parse and normalize URL
$parsedUrl = parse_url($url);
$scheme = $parsedUrl['scheme'] ?? 'http';
$host = $parsedUrl['host'] ?? 'localhost';
$port = $parsedUrl['port'] ?? null;
$path = isset($parsedUrl['path']) ? ltrim($parsedUrl['path'], '/') : '';
// Build normalized URL
$normalizedUrl = $scheme . '://' . $host;
if (($scheme === 'http' && $port !== null && $port !== 80) ||
($scheme === 'https' && $port !== null && $port !== 443)) {
$normalizedUrl .= ':' . $port;
}
$normalizedUrl .= '/' . $path;
// Get query parameters from URL
$queryParams = [];
if (isset($parsedUrl['query'])) {
parse_str($parsedUrl['query'], $queryParams);
}
// Combine OAuth params and query params (excluding oauth_signature)
$allParams = array_merge($params, $queryParams);
unset($allParams['oauth_signature']);
// Sort parameters
ksort($allParams);
// Normalize parameters
$normalizedParams = [];
foreach ($allParams as $key => $value) {
$normalizedParams[] = urlencode($key) . '=' . urlencode((string) $value);
}
$paramString = implode('&', $normalizedParams);
// Build signature base string: METHOD&URL&PARAMS
$signatureBaseString = urlencode($method) . '&' . urlencode($normalizedUrl) . '&' . urlencode($paramString);
// Build signing key (consumer secret + empty token secret)
$signingKey = urlencode($consumerSecret) . '&';
// Generate HMAC-SHA1 signature
$signature = base64_encode(hash_hmac('sha1', $signatureBaseString, $signingKey, true));
return $signature;
}
function buildAuthorizationHeader(array $oauthParams): string
{
$header = 'OAuth ';
$headerParts = [];
foreach ($oauthParams as $key => $value) {
if (strpos($key, 'oauth_') === 0) {
$headerParts[] = urlencode($key) . '="' . urlencode((string) $value) . '"';
}
}
$header .= implode(', ', $headerParts);
return $header;
}
Complete Example
Here's a complete example of making an authenticated request:
$consumerKey = 'YOUR_CONSUMER_KEY';
$consumerSecret = 'YOUR_CONSUMER_SECRET';
$apiUrl = 'https://api.bitmesh.ai/chat';
// Prepare request payload
$payload = [
'model' => 'meta-llama/Llama-3.2-3B-Instruct-Turbo',
'messages' => [
['role' => 'user', 'content' => 'What are some fun things to do with AI?'],
],
];
$jsonBody = json_encode($payload);
// Generate OAuth signature
$method = 'POST';
$oauthParams = generateOAuthParams($method, $apiUrl, $consumerKey, $consumerSecret);
$authHeader = buildAuthorizationHeader($oauthParams);
// Generate payload signature
$payloadSignature = hash('sha256', $jsonBody . $consumerKey . $oauthParams['oauth_signature']);
// Make request
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $apiUrl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: ' . $authHeader,
'Accept: application/json',
'Content-Type: application/json',
'X-Payload-Signature: ' . $payloadSignature,
],
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonBody,
]);
$response = curl_exec($ch);
curl_close($ch);
Tip: For PHP applications, we recommend using the PHP SDK which handles all signature generation automatically.
API Endpoints
Chat Completions
/chat
Create a chat completion for the given conversation. This endpoint supports all major AI models. All requests must be authenticated using OAuth 0-legged signatures (see Signature Generation).
Full URL
https://api.bitmesh.ai/chat
| Parameter | Type | Description | Required/Default |
|---|---|---|---|
messages
|
array | A list of messages comprising the conversation so far. Each message should have a "role" (system, user, or assistant) and "content". | Required |
model
|
string | The name of the model to query. Required if your API key is not restricted to a specific model. Prohibited if your API key is restricted to a specific model. | Required/Prohibited |
max_tokens
|
integer | The maximum number of tokens to generate in the completion. | Optional |
temperature
|
number | A decimal number from 0-1 that determines the degree of randomness in the response. Lower values (closer to 0) make the output more deterministic, while higher values (closer to 1) make it more random. | Optional |
frequency_penalty
|
number | A number between -2.0 and 2.0 where a positive value decreases the likelihood of repeating tokens that have already been mentioned in the text. | Optional |
repetition_penalty
|
number | A number that controls the diversity of generated text by reducing the likelihood of repeated sequences. Higher values decrease repetition. | Optional |
test
|
boolean | If true, the response will not cost any balance and will return dummy data. Useful for testing without consuming credits. | Default: false |
Example - Request Headers
Authorization: OAuth oauth_consumer_key="KO45tkb7vs6HPdjZMkzWCgpKqGrycRol", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1766991207", oauth_nonce="b2362ab1f26de6ea", oauth_version="1.0", oauth_signature="1Dk9QHMOfVpSJMUmRJjOcwqanSI%3D"
Accept: application/json
Content-Type: application/json
User-Agent: MyTestClient/1.0
X-Payload-Signature: 09898af05784a4eb7d3a68323f0d56bea18598a71f4317c535297cdf7325b867
Example - Request Body
{
"model": "meta-llama/Llama-3.2-3B-Instruct-Turbo",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What are some fun things to do with AI?"}
],
"max_tokens": 1000,
"temperature": 0.8,
"frequency_penalty": 0.5,
"repetition_penalty": 1.2,
"test": false
}
Note: The model
field is optional. If your API key is locked to a specific model, or if you omit
this field, the default model will be used.
Example - Response
{
"id": "oR7yAhG-57nCBj-9b576165af92311c",
"object": "chat.completion",
"created": 1766991277,
"model": "meta-llama/Llama-3.2-3B-Instruct-Turbo",
"prompt": [],
"choices": [
{
"finish_reason": "stop",
"seed": 1563180217642744800,
"index": 0,
"logprobs": null,
"message": {
"role": "assistant",
"content": "There are many fun things you can do with AI, depending on your interests and the type of AI you're working with. Here are some ideas to get you started:\n\n1. **Chatbots and Conversations**: Engage in natural-sounding conversations with chatbots, like me, or build your own chatbot to practice conversational AI.\n2. **Text Generation**: Write stories, poetry, or even entire books using AI-powered writing tools like language generators or writing assistants.\n3. **Image and Video Editing**: Use AI-powered photo and video editing tools to create stunning visuals, such as automatic color correction, object removal, or video stabilization.\n4. **Game Development**: Create games using AI-powered game development tools, like procedural generation or AI-powered NPCs (non-player characters).\n5. **Music Composition**: Compose music using AI-powered music tools, such as generating melodies, harmonies, or even entire songs.\n6. **Language Translation**: Practice language translation using AI-powered translation tools, like Google Translate, or build your own translation system.\n7. **Personalized Recommendations**: Use AI-powered recommendation engines to suggest movies, books, music, or products based on your interests.\n8. **Creative Writing**: Use AI-powered writing tools to generate ideas, outlines, or even entire scripts for stories, plays, or screenplays.\n9. **Art and Design**: Create art using AI-powered tools, like generating abstract art or designing logos and graphics.\n10. **Science and Research**: Use AI-powered tools to analyze data, simulate experiments, or explore complex scientific concepts.\n\nSome popular AI platforms for experimentation include:\n\n* Google's TensorFlow and Keras\n* Microsoft's Azure Machine Learning\n* IBM's Watson Studio\n* Apple's Core ML\n* OpenCV for computer vision and image processing\n\nRemember to always follow the terms of service and usage guidelines for any AI platform or tool you use.\n\nWhich of these ideas sparks your curiosity?",
"tool_calls": []
}
}
],
"usage": {
"prompt_tokens": 51,
"completion_tokens": 390,
"total_tokens": 441,
"cached_tokens": 0
}
}
Maintaining Conversation Context
Every query to the chat model is self-contained, meaning new queries won't
automatically have access to previous messages. To maintain conversation context for
long-running conversations (like chatbots), you need to include the conversation
history in the messages
array.
Use the assistant
role to provide historical context of how the model has responded to prior queries.
Include previous user messages with the user
role and previous model responses with the assistant
role.
Example - Multi-turn conversation:
{
"model": "meta-llama/Llama-3.2-3B-Instruct-Turbo",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What are some fun things to do in New York?"},
{"role": "assistant", "content": "You could visit the Empire State Building, walk through Central Park, or explore the Metropolitan Museum of Art!"},
{"role": "user", "content": "That sounds fun! Where is the Empire State Building located?"}
]
}
In this example, the model has access to the previous conversation, so it can provide context-aware responses about the Empire State Building's location. How your application stores and manages historical messages is up to you.
Code Examples
use BitmeshAI\BitmeshClient;
$consumerKey = getenv('BITMESH_CONSUMER_KEY') ?: 'YOUR_CONSUMER_KEY';
$consumerSecret = getenv('BITMESH_CONSUMER_SECRET') ?: 'YOUR_CONSUMER_SECRET';
$client = new BitmeshClient($consumerKey, $consumerSecret);
// Chat with system and user messages
$response = $client->chat([
['role' => 'system', 'content' => 'You are a helpful assistant.'],
['role' => 'user', 'content' => 'What are some fun things to do with AI?']
], 'meta-llama/Llama-3.2-3B-Instruct-Turbo', ['max_tokens' => 1000]);
Image Generate
/image
Generate an image from a text prompt using the specified model. Returns a URL to the generated image that you can fetch via the View endpoint. All requests must be authenticated using OAuth 0-legged signatures (see Signature Generation).
Full URL
https://api.bitmesh.ai/image
| Parameter | Type | Description | Required/Default |
|---|---|---|---|
prompt
|
string | The text description of the image to generate. | Required |
model
|
string | The image generation model to use (e.g.
rundiffusion/juggernaut-lightning-flux).
|
Required/Prohibited |
width
|
integer (≥ 1) | Image width in pixels. | Optional |
height
|
integer (≥ 1) | Image height in pixels. | Optional |
steps
|
integer (≥ 1) | Number of inference steps. | Optional |
seed
|
integer | Random seed for reproducibility. | Optional |
n
|
integer (≥ 1) | Number of images to generate. | Optional |
model: Required if your API key has no default model; prohibited if your API key is restricted to a specific model.
Example - Request Headers
Authorization: OAuth oauth_consumer_key="C5q9ONvO1HMJWKb80y4rJebmGjY1b8PM", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1771678805", oauth_nonce="37eac5634722b316", oauth_version="1.0", oauth_signature="j%2FkoIq2f6BIjhlziyhh8XiAOsfc%3D"
Accept: application/json
Content-Type: application/json
User-Agent: Playground/1.0
X-Payload-Signature: 977b8b64ffaecde49516eb781ba6f1cd4efbd5915073bcefa07d7d053c627291
Example - Request Body
{
"prompt": "Flying car",
"model": "rundiffusion/juggernaut-lightning-flux",
"width": 1024,
"height": 1024,
"seed": 22,
"n": 1,
"steps": 20
}
Note: The model
field is required if your API key has no default model; omit it if your key is
restricted to a specific model.
Example - Response
{
"id": "oYGByj3-2kFHot-9d166cb97de1fe05-PDX",
"model": "Rundiffusion/Juggernaut-Lightning-Flux",
"object": "list",
"data": [
{
"timings": {
"inference": 3133
},
"index": 0,
"url": "https://api.bitmesh.ai/imgrslt/Il4vHBVFuu8tiaXP"
}
]
}
The url
in the response points to the generated image. Use the View
endpoint to retrieve the image.
Code Examples
use BitmeshAI\BitmeshClient;
$consumerKey = 'YOUR_CONSUMER_KEY';
$consumerSecret = 'YOUR_CONSUMER_SECRET';
$client = new BitmeshClient($consumerKey, $consumerSecret);
// Generate image: prompt, model name, optional options (width, height, steps, seed, n)
$response = $client->image(
'Flying car',
'rundiffusion/juggernaut-lightning-flux',
['width' => 1024, 'height' => 1024, 'seed' => 22, 'n' => 1, 'steps' => 20]
);
Image View
/imgrslt/{object_id}
The url
returned from Image Generate
is a direct link to the image. No authorization is required—open it in a browser or use it
in an <img src="…"> to display the image.
https://api.bitmesh.ai/imgrslt/{object_id}
Video Generate
/video
Generate a video from a text prompt using the specified model. Returns a job with status
in_progress; use Get
to poll for completion and View
to play the result. All requests must be authenticated using OAuth 0-legged signatures (see
Signature Generation).
Full URL
https://api.bitmesh.ai/video
Parameters
| Parameter | Type | Description | Required/Default |
|---|---|---|---|
prompt
|
string (1–32000) | The text description of the video to generate. | Required |
model
|
string | The video generation model to use (e.g.
bytedance/seedance-1.0-lite).
|
Required/Prohibited |
width
|
integer (≥ 1) | Video width in pixels. | Optional |
height
|
integer (≥ 1) | Video height in pixels. | Optional |
seconds
|
string | Duration (per provider API). | Optional |
fps
|
integer (≥ 1) | Frames per second. | Optional |
steps
|
integer (10–50) | Number of inference steps. | Optional |
seed
|
integer | Random seed for reproducibility. | Optional |
guidance_scale
|
number (≥ 0) | Guidance scale for generation. | Optional |
output_format
|
string | One of MP4, WEBM. |
Optional |
output_quality
|
integer (≥ 1) | Output quality. | Optional |
negative_prompt
|
string | Text to avoid in the generated video. | Optional |
frame_images
|
array | Items: input_image (required with frame_images), frame (required with frame_images – frame index or "last"). |
Optional |
reference_images
|
array of string | Reference image URLs. | Optional |
model: Required if your API key has no default model; prohibited if your API key is restricted to a specific model.
Example - Request Headers
Authorization: OAuth oauth_consumer_key="C5q9ONvO1HMJWKb80y4rJebmGjY1b8PM", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1771679222", oauth_nonce="4a66115d496a6143", oauth_version="1.0", oauth_signature="xv1sBdprQWOL1oclkNyHeq%2F72UY%3D"
Accept: application/json
Content-Type: application/json
User-Agent: Playground/1.0
X-Payload-Signature: a0cc3b9adf74491829e8934019a1df95fc43b22f7a984bf1698331d1de1f2158
Example - Request Body
{
"prompt": "Happy happy happy cat",
"model": "bytedance/seedance-1.0-lite"
}
Note: The model
field is required if your API key has no default model; omit it if your key is
restricted to a specific model.
Example - Response
{
"object": "video",
"id": "019c804f-8e7e-7963-9429-941a293dc32a",
"model": "ByteDance/Seedance-1.0-lite",
"status": "in_progress",
"created_at": 1771679223,
"seconds": "5",
"size": "1440x1440"
}
Poll the job using the id
with the Get endpoint
until status is completed, then
use the returned URL with View.
Code Examples
use BitmeshAI\BitmeshClient;
$consumerKey = 'YOUR_CONSUMER_KEY';
$consumerSecret = 'YOUR_CONSUMER_SECRET';
$client = new BitmeshClient($consumerKey, $consumerSecret);
$response = $client->video(
'Happy happy happy cat',
'bytedance/seedance-1.0-lite'
);
Video Get
/video/{id}
Get the current status of a video generation job and the full video link when completed. Use
the id
returned from Video Generate.
When status is completed, the
response includes outputs.video_url (use View).
Full URL
https://api.bitmesh.ai/video/{id}
Example - Request
GET https://api.bitmesh.ai/video/019c804f-8e7e-7963-9429-941a293dc32a
Example - Request Headers
Authorization: OAuth oauth_consumer_key="C5q9ONvO1HMJWKb80y4rJebmGjY1b8PM", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1771679300", oauth_nonce="2d240078affe7dc1", oauth_version="1.0", oauth_signature="i4EVhFAhfVAoYo1oj4qwKgswbu4%3D"
Accept: application/json
User-Agent: Playground/1.0
X-Payload-Signature: 81372ad6fb14f51a794cde4cd673c60dfeffd970c5033cd502b7f3f58075222e
Example - Response
{
"object": "video",
"id": "019c804f-8e7e-7963-9429-941a293dc32a",
"model": "ByteDance/Seedance-1.0-lite",
"status": "completed",
"created_at": 1771679223,
"completed_at": 1771679297,
"seconds": "5",
"size": "1440x1440",
"outputs": {
"cost": 0.41164,
"video_url": "https://api.bitmesh.ai/imgrslt/ImRQ1Kv6avFi6kgL"
}
}
Code Examples
// After video() returns an id, poll status with GET /video/{id}
$statusResponse = $client->videoStatus($id);
Video View
/imgrslt/{object_id}
The video_url
returned from Video Get
(when completed) is a direct link to the video. No authorization is required—open it in a
browser or use it in a <video src="…"> to play the video.
https://api.bitmesh.ai/imgrslt/{object_id}
Error Handling
The API uses standard HTTP status codes to indicate success or failure. Error responses include a JSON body with error details.
Error Response Format
{
"error": {
"message": "Invalid API key",
"type": "authentication_error",
"code": "invalid_api_key"
}
}
Common Status Codes
200- Success400- Bad Request401- Unauthorized404- Not Found429- Rate Limit Exceeded500- Internal Server Error