External Requests API
- Base URL:
https://api.samsar.one - Canonical route prefix:
/v2/external - Auth:
Authorization: Bearer <SAMSAR_API_KEY> - Content-Type:
application/json - Billing: requests are billed to the Samsar account behind the API key using the same model pricing as the corresponding Studio action.
- Compatibility: the legacy
/external/*aliases may exist on some deployments, but new integrations should use/v2/external/*.
Use this surface when a deployed SamsarOne environment wants to call the central Samsar service as a fallback provider. Native provider credentials can still be used directly by a deployment; when they are present, they override the corresponding model settings for that deployment.
This is different from /external_users/*. External users track per-customer credits, history, and login state. External requests are one-off provider-style calls authenticated by a Samsar API key.
Validate a Samsar API key
GET /v2/external/api_key/validate
curl "https://api.samsar.one/v2/external/api_key/validate" \
-H "Authorization: Bearer $SAMSAR_API_KEY"
Success response:
{
"valid": true,
"authType": "api_key",
"email": "admin@example.com",
"remainingCredits": 12000
}
Provider capabilities
GET /v2/external/providers/capabilities
Returns the provider, model, and action capability map used by deployment onboarding.
curl "https://api.samsar.one/v2/external/providers/capabilities"
Validate deployment providers
POST /v2/external/providers/validate
Use this from the local deployment wizard to validate optional provider credentials before enabling model settings. The SDK sends credentials only to the local processor or configured Samsar API host; do not persist provider secrets in client code.
curl -X POST "https://api.samsar.one/v2/external/providers/validate" \
-H "Content-Type: application/json" \
-d '{
"samsarApiKey": "sk_live_...",
"openaiApiKey": "sk-...",
"falApiKey": "fal_...",
"runwayApiKey": "rw_..."
}'
Success response:
{
"providers": {
"samsar": {
"ok": true,
"status": "validated",
"remainingCredits": 12000
}
},
"available": {
"providers": ["samsar"],
"models": ["gpt-5.5", "gemini-3.1-pro"],
"actions": ["chat", "image", "video", "audio"]
}
}
Chat
External assistant and chat completions
The external assistant endpoints accept OpenAI-compatible chat completion payloads. They are intended for deployed Samsar environments and other integrations that use Samsar as a managed inference provider.
The /assistant/* paths below are naming aliases for the same provider-style chat handler. They are separate from the session-bound POST /v1/assistant/completion API.
Routes
Create a completion with any of these POST routes:
/v2/external/chat/v2/external/chat/completions— preferred for OpenAI-compatible integrations/v2/external/assistant/v2/external/assistant/completions
Read queued request status with any of these GET routes:
/v2/external/chat/status/v2/external/chat/completions/status/v2/external/assistant/status
The same routes are available under /api/v2/external. Legacy deployments may also expose the unversioned /external prefix. There is no /v2/external/assistant/completions/status route; use /v2/external/assistant/status or the canonical /v2/external/chat/status path.
Synchronous completion
Polling is opt-in. Without a polling control, the endpoint waits for inference and returns the raw OpenAI-compatible completion with HTTP 200.
curl -X POST "https://api.samsar.one/v2/external/chat/completions" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [
{ "role": "user", "content": "Write a launch caption for a travel reel." }
],
"max_tokens": 300
}'
The default server execution timeout is 10 minutes. stream: true is not supported. When available, billing is returned through these headers:
x-credits-chargedx-credits-remaining
Queued completion with polling
Use polling for long-running assistant work such as narrative or theme generation. It avoids holding one HTTP connection open for the entire model call and allows the request to recover after a client disconnect, network reset, or processor restart.
Generate and persist a stable client_request_id before submitting. Retry the same logical submission with the same ID if the initial response is lost.
curl -X POST "https://api.samsar.one/v2/external/assistant/completions" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"messages": [
{ "role": "user", "content": "Create a cinematic theme for this video." }
],
"response_mode": "polling",
"client_request_id": "video-67df0d8e:theme:v1",
"client_session_id": "video-67df0d8e",
"client_request_key": "theme"
}'
async: true, poll: true, or response_mode: "async" | "poll" | "polling" all enable queued mode. Prefer response_mode: "polling" for new integrations.
The canonical fields are:
| Field | Purpose |
|---|---|
client_request_id | Optional idempotency key. Make it unique for one logical request and reuse it only when retrying that request. |
client_session_id | Optional local session correlation value. It is persisted and echoed only when client_request_id is present. |
client_request_key | Optional local stage or operation name, such as theme or narrative. It is persisted and echoed only when client_request_id is present. |
timeout / timeoutMs | Optional server execution timeout in milliseconds. The default is 600000 (10 minutes). |
A queued request returns HTTP 202:
{
"request_id": "67df0d8ebc4f9d0b7f4fd123",
"requestId": "67df0d8ebc4f9d0b7f4fd123",
"status": "PENDING",
"poll_url": "/v2/external/chat/status?request_id=67df0d8ebc4f9d0b7f4fd123",
"client_request_id": "video-67df0d8e:theme:v1",
"client_session_id": "video-67df0d8e",
"client_request_key": "theme",
"created_at": "2026-07-16T13:00:00.000Z",
"updated_at": "2026-07-16T13:00:00.000Z"
}
poll_url is a relative canonical path. Store request_id as soon as it is returned. If the submit response is lost, you can still look up the request by the persisted client_request_id.
Poll by provider request ID:
curl "https://api.samsar.one/v2/external/chat/status?request_id=67df0d8ebc4f9d0b7f4fd123" \
-H "Authorization: Bearer $SAMSAR_API_KEY"
Or recover by client request ID:
curl "https://api.samsar.one/v2/external/chat/status?client_request_id=video-67df0d8e%3Atheme%3Av1" \
-H "Authorization: Bearer $SAMSAR_API_KEY"
Status reads are immediate rather than long-polling. Poll every 1–2 seconds until the request reaches a terminal state:
| Status | Meaning |
|---|---|
PENDING | Persisted and waiting to be claimed. Polling also repairs a request persisted immediately before a processor restart. |
PROCESSING | Claimed by the hosted processor. An expired worker lease can be reclaimed safely. |
COMPLETED | Terminal success. Read the OpenAI-compatible completion from response. |
FAILED | Terminal failure. Read the provider-safe details from error. |
Completed status response:
{
"request_id": "67df0d8ebc4f9d0b7f4fd123",
"status": "COMPLETED",
"response": {
"id": "chatcmpl_123",
"object": "chat.completion",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "A precise cinematic theme..."
},
"finish_reason": "stop"
}
]
},
"creditsCharged": 12,
"remainingCredits": 9988
}
Failed status response (HTTP 200):
{
"request_id": "67df0d8ebc4f9d0b7f4fd123",
"status": "FAILED",
"error": {
"message": "External assistant request failed.",
"code": null,
"status": 500
}
}
Request status is retained for 24 hours from creation. Idempotent submission replays return the original request and do not replace its payload; use a new client_request_id for an intentional retry after FAILED or COMPLETED. Fetch status to obtain completion credit headers and body fields, including after an idempotent replay.
Common errors:
400missing authentication headers, missing or invalidmessages, unsupportedstream: true, or an invalid status lookup ID.401invalid or expired credentials.402insufficient credits for a synchronous request.403the supplied credential type is not supported by this provider route.404request not found for the authenticated account.- Async provider failures are represented by HTTP
200withstatus: "FAILED"and the nestederrorobject.
Image
POST /v2/external/image/{image_route}
The external image surface mirrors the existing Image API under the /v2/external/image prefix. Common routes include:
assign_titleenhanceremove_brandingadd_image_setreceipt_templates/createreceipt_templates/querycreate_rollup_banner
Example:
curl -X POST "https://api.samsar.one/v2/external/image/enhance" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"image_url": "https://cdn.example.com/photo.png",
"resolution": "1k"
}'
Async image routes return a request_id. Poll:
curl "https://api.samsar.one/v2/external/image/status?request_id=img_enh_123" \
-H "Authorization: Bearer $SAMSAR_API_KEY"
Video
POST /v2/external/video/{video_route}
The external video surface exposes standalone media-generation routes for remote deployments that use a Samsar API key as a provider. These routes do not use the internal /v2/video/step/* pipeline and do not expose generic video-session mutation routes.
| Route | Purpose |
|---|---|
POST /v2/external/video/text_to_video | Create an express text-to-video request. |
POST /v2/external/video/image_to_video | Create an express image-to-video request from one or more public image URLs. |
POST /v2/external/video/lip_sync | Create a lip-sync video-to-video request from public video_url and audio_url inputs. |
POST /v2/external/video/sound_effect | Create a sound-effect video-to-video request from a public video_url input and prompt. |
GET /v2/external/video/status | Poll by request_id or session_id. |
GET /v2/external/video/{request_id}/status | Path-param status polling alias. |
GET /v2/external/video/status_detailed | Poll detailed status plus normalized video preview data. |
GET /v2/external/video/{request_id}/status_detailed | Path-param detailed status polling alias. |
status and status_detailed also accept POST with request_id or session_id in the JSON body.
For lip_sync and sound_effect, media inputs must be publicly reachable HTTP(S) URLs. Raw bytes, base64/data URLs, local filesystem paths, localhost URLs, and private network URLs are rejected. Docker deployments should publish local media through configured S3-compatible storage, CloudFront, or another signed/public URL strategy before calling these hosted external routes.
Example:
curl -X POST "https://api.samsar.one/v2/external/video/text_to_video" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "A cinematic product launch reel",
"image_model": "GPTIMAGE2",
"video_model": "RUNWAYML",
"duration": 10,
"aspect_ratio": "9:16",
"inference_model": "gpt-5.5"
},
"webhookUrl": "https://example.com/webhook"
}'
Image-to-video example:
curl -X POST "https://api.samsar.one/v2/external/video/image_to_video" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"image_urls": [
"https://cdn.example.com/scene-1.png",
"https://cdn.example.com/scene-2.png"
],
"prompt": "A polished destination reel",
"video_model": "RUNWAYML",
"aspect_ratio": "16:9"
}
}'
Lip-sync example:
curl -X POST "https://api.samsar.one/v2/external/video/lip_sync" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"video_url": "https://cdn.example.com/clip.mp4",
"audio_url": "https://cdn.example.com/dialogue.wav",
"lip_sync_model": "SYNCLIPSYNC",
"duration": 8,
"prompt": "Match the speaker performance to the supplied audio."
}
}'
Sound-effect example:
curl -X POST "https://api.samsar.one/v2/external/video/sound_effect" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"video_url": "https://cdn.example.com/clip.mp4",
"prompt": "Soft ocean waves and distant city ambience",
"sound_effect_model": "MIRELOAI",
"duration": 8
}
}'
Poll:
curl "https://api.samsar.one/v2/external/video/status?request_id=66ff..." \
-H "Authorization: Bearer $SAMSAR_API_KEY"
Detailed status:
curl "https://api.samsar.one/v2/external/video/status_detailed?request_id=66ff..." \
-H "Authorization: Bearer $SAMSAR_API_KEY"
Audio
GET /v2/external/audio/voices
List available audio/TTS voices keyed by provider. This endpoint is intended for external deployments that use a Samsar API key instead of native provider credentials.
This route requires a Samsar API key and does not charge credits.
Query params:
languageCode: optional Google TTS language filter, for exampleen-US.refresh: optionaltrueto refresh the Google voice catalog when the serving deployment has Google credentials.
curl "https://api.samsar.one/v2/external/audio/voices?languageCode=en-US" \
-H "Authorization: Bearer $SAMSAR_API_KEY"
The response contains providers and voicesByProvider objects keyed by provider names such as OPENAI, ELEVENLABS, PLAYAI, and GOOGLE. The Google catalog includes voices, voiceMap, count, source, and generatedAt.
POST /v2/external/audio/text_to_music
Create a hosted text-to-music request. This is intended for external or Docker deployments that use a Samsar API key instead of native ElevenLabs/FAL or Google Lyria credentials.
Supported models:
ELEVENLABS_MUSICLYRIA3(LYRIA2is accepted as an alias)
Pricing follows Studio music pricing:
| Model | Credits |
|---|---|
ELEVENLABS_MUSIC | 3 |
LYRIA3 | 3 |
curl -X POST "https://api.samsar.one/v2/external/audio/text_to_music" \
-H "Authorization: Bearer $SAMSAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": {
"prompt": "Warm cinematic synth backing track, instrumental only",
"model": "ELEVENLABS_MUSIC",
"duration": 30,
"is_instrumental": true
}
}'
Poll:
curl "https://api.samsar.one/v2/external/audio/status?request_id=66ff..." \
-H "Authorization: Bearer $SAMSAR_API_KEY"
samsar-js
import SamsarClient from 'samsar-js';
const samsar = new SamsarClient({ apiKey: process.env.SAMSAR_API_KEY! });
await samsar.validateV2ExternalSamsarApiKey();
const chat = await samsar.createV2ExternalChatCompletion({
model: 'gpt-5.5',
messages: [{ role: 'user', content: 'Write a concise product caption.' }],
});
const video = await samsar.createV2ExternalVideoRequestFromText({
prompt: 'A cinematic product launch reel',
image_model: 'GPTIMAGE2',
video_model: 'RUNWAYML',
duration: 10,
});
const status = await samsar.getV2ExternalVideoStatus(video.data.request_id!);
const imageVideo = await samsar.createV2ExternalVideoRequestFromImage({
image_url: 'https://cdn.example.com/scene-1.png',
video_model: 'RUNWAYML',
});
const lipSync = await samsar.createV2ExternalLipSyncVideo({
video_url: 'https://cdn.example.com/clip.mp4',
audio_url: 'https://cdn.example.com/dialogue.wav',
lip_sync_model: 'SYNCLIPSYNC',
});
const soundEffect = await samsar.createV2ExternalSoundEffectVideo({
video_url: 'https://cdn.example.com/clip.mp4',
prompt: 'Soft ocean waves and distant city ambience',
sound_effect_model: 'MIRELOAI',
});
const detailed = await samsar.getV2ExternalVideoStatusDetailed(lipSync.data.request_id!);
await samsar.requestV2ExternalImage('enhance', {
image_url: 'https://cdn.example.com/photo.png',
resolution: '1k',
});
const voices = await samsar.listV2ExternalAudioVoices({ languageCode: 'en-US' });
const music = await samsar.createV2ExternalTextToMusicAudio({
prompt: 'Warm cinematic synth backing track, instrumental only',
model: 'ELEVENLABS_MUSIC',
duration: 30,
is_instrumental: true,
});
const audioStatus = await samsar.getV2ExternalAudioStatus(music.data.request_id!);
The shorter aliases also use the v2 external routes:
validateSamsarApiKeygetExternalProviderCapabilitiesvalidateDeploymentProviderscreateExternalChatcreateExternalChatCompletionrequestExternalImagerequestExternalVideocreateExternalVideoRequestFromTextcreateExternalVideoRequestFromImageListcreateExternalVideoRequestFromImagecreateExternalLipSyncVideocreateExternalSoundEffectVideogetExternalImageStatusgetExternalVideoStatusgetExternalVideoStatusDetailedgetExternalVideoDetailedStatuslistExternalAudioVoicesrequestExternalAudiorequestExternalAudioRoutecreateExternalTextToMusicAudiogetExternalAudioStatus