Skip to main content
POST
/
batches
Create batch
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: JSON.stringify({
    input_file_id: '<string>',
    endpoint: '<string>',
    completion_window: '<string>',
    metadata: {},
    session_id: '<string>',
    webhook: {url: '<string>', secret: '<string>', events: ['<string>']},
    debug: {
      enabled: true,
      return_upstream_request: true,
      return_upstream_response: true,
      trace: true
    },
    provider: {
      order: ['<string>'],
      only: ['<string>'],
      ignore: ['<string>'],
      include_alpha: true,
      allow_fallbacks: true,
      require_parameters: true,
      required_execution_region: '<string>',
      required_data_region: '<string>',
      require_zero_data_retention: true,
      zdr: true,
      enforce_distillable_text: true,
      quantizations: ['<string>'],
      sort: '<string>',
      max_price: {prompt: 123, completion: 123, image: 123, audio: 123, request: 123},
      preferred_min_throughput: 123,
      preferred_max_latency: 123
    }
  })
};

fetch('https://api.phaseo.ai/v1/batches', options)
  .then(res => res.json())
  .then(res => console.log(res))
  .catch(err => console.error(err));
import requests

url = "https://api.phaseo.ai/v1/batches"

payload = {
"input_file_id": "<string>",
"endpoint": "<string>",
"completion_window": "<string>",
"metadata": {},
"session_id": "<string>",
"webhook": {
"url": "<string>",
"secret": "<string>",
"events": ["<string>"]
},
"debug": {
"enabled": True,
"return_upstream_request": True,
"return_upstream_response": True,
"trace": True
},
"provider": {
"order": ["<string>"],
"only": ["<string>"],
"ignore": ["<string>"],
"include_alpha": True,
"allow_fallbacks": True,
"require_parameters": True,
"required_execution_region": "<string>",
"required_data_region": "<string>",
"require_zero_data_retention": True,
"zdr": True,
"enforce_distillable_text": True,
"quantizations": ["<string>"],
"sort": "<string>",
"max_price": {
"prompt": 123,
"completion": 123,
"image": 123,
"audio": 123,
"request": 123
},
"preferred_min_throughput": 123,
"preferred_max_latency": 123
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
curl --request POST \
--url https://api.phaseo.ai/v1/batches \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"input_file_id": "<string>",
"endpoint": "<string>",
"completion_window": "<string>",
"metadata": {},
"session_id": "<string>",
"webhook": {
"url": "<string>",
"secret": "<string>",
"events": [
"<string>"
]
},
"debug": {
"enabled": true,
"return_upstream_request": true,
"return_upstream_response": true,
"trace": true
},
"provider": {
"order": [
"<string>"
],
"only": [
"<string>"
],
"ignore": [
"<string>"
],
"include_alpha": true,
"allow_fallbacks": true,
"require_parameters": true,
"required_execution_region": "<string>",
"required_data_region": "<string>",
"require_zero_data_retention": true,
"zdr": true,
"enforce_distillable_text": true,
"quantizations": [
"<string>"
],
"sort": "<string>",
"max_price": {
"prompt": 123,
"completion": 123,
"image": 123,
"audio": 123,
"request": 123
},
"preferred_min_throughput": 123,
"preferred_max_latency": 123
}
}
'
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.phaseo.ai/v1/batches"

payload := strings.NewReader("{\n \"input_file_id\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"completion_window\": \"<string>\",\n \"metadata\": {},\n \"session_id\": \"<string>\",\n \"webhook\": {\n \"url\": \"<string>\",\n \"secret\": \"<string>\",\n \"events\": [\n \"<string>\"\n ]\n },\n \"debug\": {\n \"enabled\": true,\n \"return_upstream_request\": true,\n \"return_upstream_response\": true,\n \"trace\": true\n },\n \"provider\": {\n \"order\": [\n \"<string>\"\n ],\n \"only\": [\n \"<string>\"\n ],\n \"ignore\": [\n \"<string>\"\n ],\n \"include_alpha\": true,\n \"allow_fallbacks\": true,\n \"require_parameters\": true,\n \"required_execution_region\": \"<string>\",\n \"required_data_region\": \"<string>\",\n \"require_zero_data_retention\": true,\n \"zdr\": true,\n \"enforce_distillable_text\": true,\n \"quantizations\": [\n \"<string>\"\n ],\n \"sort\": \"<string>\",\n \"max_price\": {\n \"prompt\": 123,\n \"completion\": 123,\n \"image\": 123,\n \"audio\": 123,\n \"request\": 123\n },\n \"preferred_min_throughput\": 123,\n \"preferred_max_latency\": 123\n }\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.phaseo.ai/v1/batches")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"input_file_id\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"completion_window\": \"<string>\",\n \"metadata\": {},\n \"session_id\": \"<string>\",\n \"webhook\": {\n \"url\": \"<string>\",\n \"secret\": \"<string>\",\n \"events\": [\n \"<string>\"\n ]\n },\n \"debug\": {\n \"enabled\": true,\n \"return_upstream_request\": true,\n \"return_upstream_response\": true,\n \"trace\": true\n },\n \"provider\": {\n \"order\": [\n \"<string>\"\n ],\n \"only\": [\n \"<string>\"\n ],\n \"ignore\": [\n \"<string>\"\n ],\n \"include_alpha\": true,\n \"allow_fallbacks\": true,\n \"require_parameters\": true,\n \"required_execution_region\": \"<string>\",\n \"required_data_region\": \"<string>\",\n \"require_zero_data_retention\": true,\n \"zdr\": true,\n \"enforce_distillable_text\": true,\n \"quantizations\": [\n \"<string>\"\n ],\n \"sort\": \"<string>\",\n \"max_price\": {\n \"prompt\": 123,\n \"completion\": 123,\n \"image\": 123,\n \"audio\": 123,\n \"request\": 123\n },\n \"preferred_min_throughput\": 123,\n \"preferred_max_latency\": 123\n }\n}")
.asString();
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.phaseo.ai/v1/batches",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'input_file_id' => '<string>',
'endpoint' => '<string>',
'completion_window' => '<string>',
'metadata' => [

],
'session_id' => '<string>',
'webhook' => [
'url' => '<string>',
'secret' => '<string>',
'events' => [
'<string>'
]
],
'debug' => [
'enabled' => true,
'return_upstream_request' => true,
'return_upstream_response' => true,
'trace' => true
],
'provider' => [
'order' => [
'<string>'
],
'only' => [
'<string>'
],
'ignore' => [
'<string>'
],
'include_alpha' => true,
'allow_fallbacks' => true,
'require_parameters' => true,
'required_execution_region' => '<string>',
'required_data_region' => '<string>',
'require_zero_data_retention' => true,
'zdr' => true,
'enforce_distillable_text' => true,
'quantizations' => [
'<string>'
],
'sort' => '<string>',
'max_price' => [
'prompt' => 123,
'completion' => 123,
'image' => 123,
'audio' => 123,
'request' => 123
],
'preferred_min_throughput' => 123,
'preferred_max_latency' => 123
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
require 'uri'
require 'net/http'

url = URI("https://api.phaseo.ai/v1/batches")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"input_file_id\": \"<string>\",\n \"endpoint\": \"<string>\",\n \"completion_window\": \"<string>\",\n \"metadata\": {},\n \"session_id\": \"<string>\",\n \"webhook\": {\n \"url\": \"<string>\",\n \"secret\": \"<string>\",\n \"events\": [\n \"<string>\"\n ]\n },\n \"debug\": {\n \"enabled\": true,\n \"return_upstream_request\": true,\n \"return_upstream_response\": true,\n \"trace\": true\n },\n \"provider\": {\n \"order\": [\n \"<string>\"\n ],\n \"only\": [\n \"<string>\"\n ],\n \"ignore\": [\n \"<string>\"\n ],\n \"include_alpha\": true,\n \"allow_fallbacks\": true,\n \"require_parameters\": true,\n \"required_execution_region\": \"<string>\",\n \"required_data_region\": \"<string>\",\n \"require_zero_data_retention\": true,\n \"zdr\": true,\n \"enforce_distillable_text\": true,\n \"quantizations\": [\n \"<string>\"\n ],\n \"sort\": \"<string>\",\n \"max_price\": {\n \"prompt\": 123,\n \"completion\": 123,\n \"image\": 123,\n \"audio\": 123,\n \"request\": 123\n },\n \"preferred_min_throughput\": 123,\n \"preferred_max_latency\": 123\n }\n}"

response = http.request(request)
puts response.read_body
{
  "id": "<string>",
  "native_batch_id": "<string>",
  "object": "<string>",
  "endpoint": "<string>",
  "errors": {},
  "input_file_id": "<string>",
  "completion_window": "<string>",
  "status": "<string>",
  "progress": 50,
  "polling_url": "<string>",
  "websocket_url": "<string>",
  "cancel_url": "<string>",
  "output_file_id": "<string>",
  "error_file_id": "<string>",
  "created_at": 123,
  "in_progress_at": 123,
  "expires_at": 123,
  "finalizing_at": 123,
  "completed_at": 123,
  "failed_at": 123,
  "expired_at": 123,
  "cancelling_at": 123,
  "cancelled_at": 123,
  "request_counts": {
    "total": 123,
    "completed": 123,
    "failed": 123
  },
  "metadata": {},
  "request_id": "<string>",
  "provider": "<string>",
  "session_id": "<string>",
  "webhook": {
    "url": "<string>",
    "events": [
      "<string>"
    ],
    "has_secret": true,
    "delivery": {
      "total_attempts": 123,
      "delivered_events": 123,
      "delivered_event_types": [
        "video.completed"
      ],
      "pending_retries": 123,
      "next_retry_at": "<string>",
      "last_attempt_at": "<string>",
      "last_response_status": 123,
      "last_delivered_at": "<string>",
      "last_failure_at": "<string>",
      "last_error_message": "<string>"
    },
    "attempts": [
      {
        "id": "<string>",
        "delivery_key": "video.completed",
        "event_type": "video.completed",
        "attempt_number": 123,
        "max_attempts": 123,
        "tried_at": "<string>",
        "delivered_at": "<string>",
        "next_retry_at": "<string>",
        "response_status": 123,
        "error_message": "<string>",
        "response_body_preview": "<string>"
      }
    ]
  },
  "next_webhook_retry_at": "<string>",
  "last_webhook_progress": 123,
  "last_webhook_progress_at": "<string>",
  "last_webhook_dispatched_at": "<string>",
  "finalized_at": "<string>",
  "pricing_lines": [
    {}
  ],
  "billing": {
    "currency": "<string>",
    "billed": true,
    "charged": true,
    "reason": "<string>",
    "reservation_id": "<string>",
    "reservation_status": "<string>",
    "estimated_provider_cost": "<string>",
    "estimated_user_cost": "<string>",
    "settled_provider_cost": "<string>",
    "settled_user_cost": "<string>",
    "estimated_nanos": 123,
    "reserved_nanos": 123,
    "estimation_truncated": true,
    "estimation_sample_size": 123,
    "estimation_total_rows": 123,
    "total_nanos": 123,
    "cost_nanos": 123,
    "cost_usd": 123,
    "finalized_at": "<string>",
    "pricing_breakdown": {}
  }
}
{
"error": "error_type",
"ok": false,
"message": "Human-readable error message",
"description": "Additional error details.",
"generation_id": "G-abc123",
"status_code": 502,
"error_type": "system",
"error_origin": "upstream",
"reason": "all_candidates_failed",
"attempt_count": 2,
"failed_providers": [
"google-ai-studio",
"openai"
],
"failed_statuses": [
403,
429
],
"upstream_error": {
"code": "PERMISSION_DENIED",
"message": "The caller does not have permission.",
"description": "<string>",
"param": "<string>"
},
"failure_sample": [
{
"provider": "<string>",
"type": "<string>",
"status": 123,
"upstream_error_code": "<string>",
"upstream_error_message": "<string>",
"upstream_error_description": "<string>",
"upstream_error_param": "<string>",
"upstream_payload_preview": "<string>",
"retryable": true
}
],
"provider_failure_diagnostics": {
"hint": "<string>",
"provider": "<string>"
},
"routing_diagnostics": {
"filterStages": [
{
"stage": "<string>",
"beforeCount": 123,
"afterCount": 123,
"droppedProviders": [
{
"providerId": "<string>",
"reason": "<string>"
}
]
}
]
},
"provider_candidate_diagnostics": {
"totalProviders": 123,
"supportsEndpointCount": 123,
"candidateCount": 123,
"droppedUnsupportedEndpoint": [
"<string>"
],
"droppedMissingAdapter": [
{
"providerId": "<string>",
"endpoint": "<string>"
}
]
},
"provider_enablement": {
"capability": "<string>",
"providersBefore": [
"<string>"
],
"providersAfter": [
"<string>"
],
"dropped": [
{
"providerId": "<string>",
"reason": "<string>"
}
]
},
"missing_pricing_providers": [
"<string>"
],
"provider_payment_required_provider": "openai",
"provider_payment_required_support_notice": "Our upstream provider billing appears to be unavailable. If this persists, contact support.",
"details": [
{}
]
}
Creates an async batch job. Phaseo also accepts these extra fields:
  • session_id to group the batch with related requests in logs and activity views
  • webhook to configure async notifications when the batch transitions state.
  • metadata to persist caller-defined tags alongside the batch.
Webhook events may use generic job.* names or matching batch.* names. Include job.progress or batch.progress to receive progress notifications when the provider reports request counts. If omitted, terminal job.completed, job.failed, job.cancelled, and job.expired events are used. If supplied, at least one event must be valid for batch jobs; cross-kind-only or malformed event lists are rejected. Webhook callback URLs must use HTTPS. Literal private, loopback, link-local, and wildcard hosts are rejected; http://localhost, http://127.0.0.1, and http://[::1] are allowed only for local development callbacks. Use GET /batches/models to discover batch-capable models and supported batch parameters, GET /batches to list owned batch jobs, GET /batches/{batch_id} to poll status, and POST /batches/{batch_id}/cancel to stop a pending or processing batch. Persist and poll the gateway-owned response id. When Phaseo also returns native_batch_id, that value is the provider-native id used for upstream correlation; do not use it in Phaseo polling, websocket, or cancellation URLs unless it is also the gateway id. Batch creation reserves gateway credits before submitting upstream when the input can be priced. If the gateway cannot read the input file or resolve pricing, creation fails before provider submission instead of starting unreserved work. Batch responses can also include:
  • request_id
  • native_batch_id when the provider id differs from the gateway id
  • provider
  • echoed session_id
  • sanitized webhook configuration and delivery state
  • lifecycle_status, polling_url, and cancel_url
  • billing reservation and settlement state, including held estimates before final settlement
  • terminal pricing_lines
Related endpoints:

Authorizations

Authorization
string
header
required

Bearer token authentication

Body

application/json
input_file_id
string
required
endpoint
string
required
completion_window
string
metadata
object
session_id
string

Unique identifier for grouping related requests (for example, a conversation or agent workflow) for observability.

Maximum string length: 256
webhook
object
debug
object

Gateway debug controls. These flags are never forwarded upstream.

provider
object

Provider routing preferences for gateway selection.

Response

Batch status response

id
string
native_batch_id
string | null

Provider-native batch id when it differs from the gateway-owned id.

object
string
endpoint
string
errors
object
input_file_id
string
completion_window
string
status
string
lifecycle_status
enum<string>

Normalized async lifecycle status for polling, websocket, and webhook consumers.

Available options:
pending,
running,
completed,
failed,
cancelled,
expired
progress
integer

Coarse batch completion percentage derived from provider request counts when available. Completed batches report 100.

Required range: 0 <= x <= 100
polling_url
string<uri>
websocket_url
string<uri>

WebSocket URL for subscribing to normalized async job lifecycle updates.

cancel_url
string<uri> | null
output_file_id
string
error_file_id
string
created_at
integer
in_progress_at
integer
expires_at
integer
finalizing_at
integer
completed_at
integer
failed_at
integer
expired_at
integer
cancelling_at
integer
cancelled_at
integer
request_counts
object
metadata
object
request_id
string
provider
string
session_id
string
webhook
object

Sanitized async webhook configuration plus delivery state. Secrets are never returned; has_secret indicates whether signed deliveries are enabled. Signed deliveries include x-phaseo-signature, x-phaseo-timestamp, x-phaseo-event-id, x-phaseo-event-type, x-phaseo-delivery-key, x-phaseo-attempt, and x-phaseo-max-attempts headers.

next_webhook_retry_at
string | null
last_webhook_progress
number | null
last_webhook_progress_at
string | null
last_webhook_dispatched_at
string | null
finalized_at
string | null
pricing_lines
object[]
billing
object
Last modified on July 9, 2026