diff --git a/specification/DigitalOcean-public.v2.yaml b/specification/DigitalOcean-public.v2.yaml index ea5fca026..3c68c1bd1 100644 --- a/specification/DigitalOcean-public.v2.yaml +++ b/specification/DigitalOcean-public.v2.yaml @@ -3981,6 +3981,23 @@ paths: post: $ref: 'resources/inference/inference_async_invoke.yml' + + /v1/audio/speech: + post: + $ref: 'resources/inference/inference_create_speech.yml' + + /v1/videos: + post: + $ref: 'resources/inference/inference_create_video.yml' + + /v1/videos/{video_id}: + get: + $ref: 'resources/inference/inference_get_video.yml' + + /v1/videos/{video_id}/content: + get: + $ref: 'resources/inference/inference_get_video_content.yml' + /v1/batches/files: post: $ref: 'resources/inference/inference_create_batch_file.yml' diff --git a/specification/resources/inference/examples/curl/inference_create_speech.yml b/specification/resources/inference/examples/curl/inference_create_speech.yml new file mode 100644 index 000000000..3ab78b694 --- /dev/null +++ b/specification/resources/inference/examples/curl/inference_create_speech.yml @@ -0,0 +1,13 @@ +lang: cURL +source: |- + curl -sS https://inference.do-ai.run/v1/audio/speech \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "qwen3-tts-voicedesign", + "input": "Hello, world!", + "voice": "alloy", + "response_format": "mp3", + "instructions": "Speak naturally." + }' \ + --output output.mp3 diff --git a/specification/resources/inference/examples/curl/inference_create_video.yml b/specification/resources/inference/examples/curl/inference_create_video.yml new file mode 100644 index 000000000..d3b1913ba --- /dev/null +++ b/specification/resources/inference/examples/curl/inference_create_video.yml @@ -0,0 +1,11 @@ +lang: cURL +source: |- + curl -X POST https://inference.do-ai.run/v1/videos \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "wan2-2-t2v-a14b", + "prompt": "Two anthropomorphic cats in boxing gear fight intensely on a spotlighted stage", + "size": "1280x720", + "fps": 16 + }' diff --git a/specification/resources/inference/examples/curl/inference_get_video.yml b/specification/resources/inference/examples/curl/inference_get_video.yml new file mode 100644 index 000000000..e77bcda2e --- /dev/null +++ b/specification/resources/inference/examples/curl/inference_get_video.yml @@ -0,0 +1,4 @@ +lang: cURL +source: |- + curl https://inference.do-ai.run/v1/videos/$VIDEO_ID \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" diff --git a/specification/resources/inference/examples/curl/inference_get_video_content.yml b/specification/resources/inference/examples/curl/inference_get_video_content.yml new file mode 100644 index 000000000..5bfd35e63 --- /dev/null +++ b/specification/resources/inference/examples/curl/inference_get_video_content.yml @@ -0,0 +1,5 @@ +lang: cURL +source: |- + curl https://inference.do-ai.run/v1/videos/$VIDEO_ID/content \ + -H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \ + --output output.mp4 diff --git a/specification/resources/inference/examples/dots/inference_create_speech.yml b/specification/resources/inference/examples/dots/inference_create_speech.yml new file mode 100644 index 000000000..6364f2dc9 --- /dev/null +++ b/specification/resources/inference/examples/dots/inference_create_speech.yml @@ -0,0 +1,19 @@ +lang: JavaScript +source: |- + import { writeFileSync } from "fs"; + import { InferenceClient } from "@digitalocean/dots"; + + const client = new InferenceClient({ + apiKey: process.env.DIGITALOCEAN_TOKEN, + }); + + const response = await client.audio.speech.create({ + model: "qwen3-tts-voicedesign", + input: "Hello, world!", + voice: "alloy", + response_format: "mp3", + instructions: "Speak naturally.", + }); + + const audioBytes = Buffer.from(response.data[0].b64_json, "base64"); + writeFileSync("output.mp3", audioBytes); diff --git a/specification/resources/inference/examples/dots/inference_create_video.yml b/specification/resources/inference/examples/dots/inference_create_video.yml new file mode 100644 index 000000000..4212f19c4 --- /dev/null +++ b/specification/resources/inference/examples/dots/inference_create_video.yml @@ -0,0 +1,16 @@ +lang: JavaScript +source: |- + import { InferenceClient } from "@digitalocean/dots"; + + const client = new InferenceClient({ + apiKey: process.env.DIGITALOCEAN_TOKEN, + }); + + const job = await client.video.generations.create({ + model: "wan2-2-t2v-a14b", + prompt: "Two anthropomorphic cats in boxing gear fight intensely on a spotlighted stage", + size: "1280x720", + fps: 16, + }); + + console.log(job.id, job.status); diff --git a/specification/resources/inference/examples/dots/inference_get_video.yml b/specification/resources/inference/examples/dots/inference_get_video.yml new file mode 100644 index 000000000..322b07ba9 --- /dev/null +++ b/specification/resources/inference/examples/dots/inference_get_video.yml @@ -0,0 +1,10 @@ +lang: JavaScript +source: |- + import { InferenceClient } from "@digitalocean/dots"; + + const client = new InferenceClient({ + apiKey: process.env.DIGITALOCEAN_TOKEN, + }); + + const job = await client.video.generations.retrieve(process.env.VIDEO_ID); + console.log(job.id, job.status); diff --git a/specification/resources/inference/examples/dots/inference_get_video_content.yml b/specification/resources/inference/examples/dots/inference_get_video_content.yml new file mode 100644 index 000000000..a2e4e31db --- /dev/null +++ b/specification/resources/inference/examples/dots/inference_get_video_content.yml @@ -0,0 +1,11 @@ +lang: JavaScript +source: |- + import { writeFileSync } from "fs"; + import { InferenceClient } from "@digitalocean/dots"; + + const client = new InferenceClient({ + apiKey: process.env.DIGITALOCEAN_TOKEN, + }); + + const content = await client.video.generations.content(process.env.VIDEO_ID); + writeFileSync("output.mp4", Buffer.from(await content.arrayBuffer())); diff --git a/specification/resources/inference/examples/go/agentInference_create_chat_completion.yml b/specification/resources/inference/examples/go/agentInference_create_chat_completion.yml index aece2c5b9..d00fba084 100644 --- a/specification/resources/inference/examples/go/agentInference_create_chat_completion.yml +++ b/specification/resources/inference/examples/go/agentInference_create_chat_completion.yml @@ -32,6 +32,6 @@ source: |- } if msg := completion.Choices[0].Message.Content; msg != nil { - fmt.Println(*msg) + fmt.Println(msg.Text()) } } diff --git a/specification/resources/inference/examples/go/inference_create_chat_completion.yml b/specification/resources/inference/examples/go/inference_create_chat_completion.yml index 95bb3dc9c..2d9fc15a3 100644 --- a/specification/resources/inference/examples/go/inference_create_chat_completion.yml +++ b/specification/resources/inference/examples/go/inference_create_chat_completion.yml @@ -25,6 +25,6 @@ source: |- } if msg := completion.Choices[0].Message.Content; msg != nil { - fmt.Println(*msg) + fmt.Println(msg.Text()) } } diff --git a/specification/resources/inference/examples/go/inference_create_chat_completion_kb.yml b/specification/resources/inference/examples/go/inference_create_chat_completion_kb.yml new file mode 100644 index 000000000..bf7f3fc30 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_chat_completion_kb.yml @@ -0,0 +1,37 @@ +lang: Go +label: Knowledge base +source: |- + package main + + import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + completion, _, err := client.Chat.Completions.New(ctx, &godo.ChatCompletionNewParams{ + Model: "openai-gpt-oss-20b", + Messages: []godo.ChatCompletionMessage{ + godo.UserMessage("What are some features of DigitalOcean Inference?"), + }, + Tools: []godo.ChatCompletionTool{ + godo.ChatKnowledgeBaseRetrievalTool(os.Getenv("KNOWLEDGE_BASE_ID")), + }, + ToolChoice: json.RawMessage(`"auto"`), + MaxTokens: godo.PtrTo(1024), + }) + if err != nil { + panic(err) + } + + if msg := completion.Choices[0].Message.Content; msg != nil { + fmt.Println(msg.Text()) + } + } diff --git a/specification/resources/inference/examples/go/inference_create_chat_completion_mcp.yml b/specification/resources/inference/examples/go/inference_create_chat_completion_mcp.yml new file mode 100644 index 000000000..88d8d4c05 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_chat_completion_mcp.yml @@ -0,0 +1,42 @@ +lang: Go +label: MCP tool +source: |- + package main + + import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + completion, _, err := client.Chat.Completions.New(ctx, &godo.ChatCompletionNewParams{ + Model: "openai-gpt-oss-20b", + Messages: []godo.ChatCompletionMessage{ + godo.UserMessage("Fetch my DigitalOcean account information and summarize it in 2 bullets."), + }, + Tools: []godo.ChatCompletionTool{ + godo.ChatMCPTool(godo.MCPToolParams{ + ServerLabel: "digitalocean", + ServerURL: "https://accounts.mcp.digitalocean.com/mcp", + Authorization: "Bearer " + os.Getenv("DIGITALOCEAN_API_TOKEN"), + AllowedTools: []string{"account-get-information"}, + }), + }, + ToolChoice: json.RawMessage(`"required"`), + MaxTokens: godo.PtrTo(512), + }) + if err != nil { + panic(err) + } + + if msg := completion.Choices[0].Message.Content; msg != nil { + fmt.Println(msg.Text()) + } + } diff --git a/specification/resources/inference/examples/go/inference_create_chat_completion_vlm.yml b/specification/resources/inference/examples/go/inference_create_chat_completion_vlm.yml new file mode 100644 index 000000000..58439273b --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_chat_completion_vlm.yml @@ -0,0 +1,41 @@ +lang: Go +label: Vision (VLM) +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + // IMAGE_URL may be an HTTPS URL or a data:image/...;base64,... URI. + imageURL := os.Getenv("IMAGE_URL") + if imageURL == "" { + imageURL = "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Online_Bicycles.jpg/640px-Online_Bicycles.jpg" + } + + completion, _, err := client.Chat.Completions.New(ctx, &godo.ChatCompletionNewParams{ + Model: "nemotron-nano-12b-v2-vl", + Messages: []godo.ChatCompletionMessage{ + godo.UserMessageParts( + godo.TextPart("Describe this image."), + godo.ImageURLPart(imageURL), + ), + }, + MaxTokens: godo.PtrTo(512), + }) + if err != nil { + panic(err) + } + + if msg := completion.Choices[0].Message.Content; msg != nil { + fmt.Println(msg.Text()) + } + } diff --git a/specification/resources/inference/examples/go/inference_create_response_model_synthesis.yml b/specification/resources/inference/examples/go/inference_create_response_model_synthesis.yml new file mode 100644 index 000000000..49b92b9db --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_response_model_synthesis.yml @@ -0,0 +1,33 @@ +lang: Go +label: Model synthesis +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + resp, _, err := client.Responses.New(ctx, &godo.ResponseNewParams{ + Model: "openai-gpt-oss-20b", + Input: "Compare approaches for reducing inference latency.", + Tools: []godo.ResponseTool{ + godo.ModelSynthesisTool(godo.ModelSynthesisToolParams{ + Preset: "balanced", + }), + }, + MaxOutputTokens: godo.PtrTo(1024), + }) + if err != nil { + panic(err) + } + + fmt.Println(resp.OutputText()) + } diff --git a/specification/resources/inference/examples/go/inference_create_response_tool_search.yml b/specification/resources/inference/examples/go/inference_create_response_tool_search.yml new file mode 100644 index 000000000..40ac3c803 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_response_tool_search.yml @@ -0,0 +1,38 @@ +lang: Go +label: Tool search +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + resp, _, err := client.Responses.New(ctx, &godo.ResponseNewParams{ + Model: "openai-gpt-5.5", + Input: "Compare the current weather in zip code 94107 and 10001.", + Tools: []godo.ResponseTool{ + godo.FunctionTool("get_weather", "Get weather for a zip code", map[string]interface{}{ + "type": "object", + "properties": map[string]interface{}{ + "zip": map[string]interface{}{"type": "string"}, + }, + "required": []string{"zip"}, + }), + godo.ToolSearchTool(), + }, + MaxOutputTokens: godo.PtrTo(1024), + }) + if err != nil { + panic(err) + } + + fmt.Println(resp.OutputText()) + } diff --git a/specification/resources/inference/examples/go/inference_create_response_web_fetch.yml b/specification/resources/inference/examples/go/inference_create_response_web_fetch.yml new file mode 100644 index 000000000..7d7130537 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_response_web_fetch.yml @@ -0,0 +1,31 @@ +lang: Go +label: Web fetch +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + resp, _, err := client.Responses.New(ctx, &godo.ResponseNewParams{ + Model: "openai-gpt-oss-20b", + Input: "Summarize https://www.digitalocean.com/pricing", + Tools: []godo.ResponseTool{ + godo.WebFetchTool(godo.PtrTo(3)), + }, + MaxOutputTokens: godo.PtrTo(1024), + }) + if err != nil { + panic(err) + } + + fmt.Println(resp.OutputText()) + } diff --git a/specification/resources/inference/examples/go/inference_create_response_web_search.yml b/specification/resources/inference/examples/go/inference_create_response_web_search.yml new file mode 100644 index 000000000..6a3486f8f --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_response_web_search.yml @@ -0,0 +1,31 @@ +lang: Go +label: Web search +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + resp, _, err := client.Responses.New(ctx, &godo.ResponseNewParams{ + Model: "openai-gpt-oss-20b", + Input: "What are the latest pricing changes for DigitalOcean Droplets?", + Tools: []godo.ResponseTool{ + godo.WebSearchTool(godo.PtrTo(3), godo.PtrTo(5)), + }, + MaxOutputTokens: godo.PtrTo(1024), + }) + if err != nil { + panic(err) + } + + fmt.Println(resp.OutputText()) + } diff --git a/specification/resources/inference/examples/go/inference_create_speech.yml b/specification/resources/inference/examples/go/inference_create_speech.yml new file mode 100644 index 000000000..03b2e1b0c --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_speech.yml @@ -0,0 +1,36 @@ +lang: Go +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + speech, _, err := client.Audio.Speech.New(ctx, &godo.SpeechNewParams{ + Model: "qwen3-tts-voicedesign", + Input: "Hello, world!", + Voice: "alloy", + ResponseFormat: "mp3", + Instructions: "Speak naturally.", + }) + if err != nil { + panic(err) + } + + audioBytes, err := speech.Bytes() + if err != nil { + panic(err) + } + if err := os.WriteFile("output.mp3", audioBytes, 0644); err != nil { + panic(err) + } + fmt.Println("Wrote output.mp3") + } diff --git a/specification/resources/inference/examples/go/inference_create_video.yml b/specification/resources/inference/examples/go/inference_create_video.yml new file mode 100644 index 000000000..1457a0bf2 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_create_video.yml @@ -0,0 +1,28 @@ +lang: Go +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + job, _, err := client.Video.Generations.Create(ctx, &godo.VideoGenerateParams{ + Model: "wan2-2-t2v-a14b", + Prompt: "Two anthropomorphic cats in boxing gear fight intensely on a spotlighted stage", + Size: "1280x720", + FPS: godo.PtrTo(16), + }) + if err != nil { + panic(err) + } + + fmt.Println(job.ID, job.Status) + } diff --git a/specification/resources/inference/examples/go/inference_get_video.yml b/specification/resources/inference/examples/go/inference_get_video.yml new file mode 100644 index 000000000..6a2458c03 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_get_video.yml @@ -0,0 +1,23 @@ +lang: Go +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + job, _, err := client.Video.Generations.Get(ctx, os.Getenv("VIDEO_ID")) + if err != nil { + panic(err) + } + + fmt.Println(job.ID, job.Status) + } diff --git a/specification/resources/inference/examples/go/inference_get_video_content.yml b/specification/resources/inference/examples/go/inference_get_video_content.yml new file mode 100644 index 000000000..601bfdac7 --- /dev/null +++ b/specification/resources/inference/examples/go/inference_get_video_content.yml @@ -0,0 +1,25 @@ +lang: Go +source: |- + package main + + import ( + "context" + "fmt" + "os" + + "github.com/digitalocean/godo" + ) + + func main() { + client := godo.NewFromToken(os.Getenv("DIGITALOCEAN_TOKEN")) + ctx := context.Background() + + raw, _, err := client.Video.Generations.Content(ctx, os.Getenv("VIDEO_ID")) + if err != nil { + panic(err) + } + if err := os.WriteFile("output.mp4", raw, 0644); err != nil { + panic(err) + } + fmt.Println("Wrote output.mp4") + } diff --git a/specification/resources/inference/examples/python/inference_create_speech.yml b/specification/resources/inference/examples/python/inference_create_speech.yml new file mode 100644 index 000000000..46e28a161 --- /dev/null +++ b/specification/resources/inference/examples/python/inference_create_speech.yml @@ -0,0 +1,19 @@ +lang: Python +source: |- + import base64 + import os + from pydo.inference import Client + + client = Client(token=os.environ.get("DIGITALOCEAN_TOKEN")) + + response = client.audio.speech.create( + model="qwen3-tts-voicedesign", + input="Hello, world!", + voice="alloy", + response_format="mp3", + instructions="Speak naturally.", + ) + + audio_bytes = base64.b64decode(response.data[0].b64_json) + with open("output.mp3", "wb") as f: + f.write(audio_bytes) diff --git a/specification/resources/inference/examples/python/inference_create_video.yml b/specification/resources/inference/examples/python/inference_create_video.yml new file mode 100644 index 000000000..2402b6fce --- /dev/null +++ b/specification/resources/inference/examples/python/inference_create_video.yml @@ -0,0 +1,15 @@ +lang: Python +source: |- + import os + from pydo.inference import Client + + client = Client(token=os.environ.get("DIGITALOCEAN_TOKEN")) + + job = client.video.generations.create( + model="wan2-2-t2v-a14b", + prompt="Two anthropomorphic cats in boxing gear fight intensely on a spotlighted stage", + size="1280x720", + fps=16, + ) + + print(job.id, job.status) diff --git a/specification/resources/inference/examples/python/inference_get_video.yml b/specification/resources/inference/examples/python/inference_get_video.yml new file mode 100644 index 000000000..614d67400 --- /dev/null +++ b/specification/resources/inference/examples/python/inference_get_video.yml @@ -0,0 +1,9 @@ +lang: Python +source: |- + import os + from pydo.inference import Client + + client = Client(token=os.environ.get("DIGITALOCEAN_TOKEN")) + + job = client.video.generations.retrieve(os.environ["VIDEO_ID"]) + print(job.id, job.status) diff --git a/specification/resources/inference/examples/python/inference_get_video_content.yml b/specification/resources/inference/examples/python/inference_get_video_content.yml new file mode 100644 index 000000000..fef181f19 --- /dev/null +++ b/specification/resources/inference/examples/python/inference_get_video_content.yml @@ -0,0 +1,11 @@ +lang: Python +source: |- + import os + import requests + + headers = {"Authorization": f"Bearer {os.environ['DIGITALOCEAN_TOKEN']}"} + url = f"https://inference.do-ai.run/v1/videos/{os.environ['VIDEO_ID']}/content" + resp = requests.get(url, headers=headers) + resp.raise_for_status() + with open("output.mp4", "wb") as f: + f.write(resp.content) diff --git a/specification/resources/inference/inference_create_chat_completion.yml b/specification/resources/inference/inference_create_chat_completion.yml index 5fefca8c5..f8dc1de76 100644 --- a/specification/resources/inference/inference_create_chat_completion.yml +++ b/specification/resources/inference/inference_create_chat_completion.yml @@ -42,6 +42,9 @@ x-codeSamples: - $ref: 'examples/curl/inference_create_chat_completion.yml' - $ref: 'examples/python/inference_create_chat_completion.yml' - $ref: 'examples/go/inference_create_chat_completion.yml' + - $ref: 'examples/go/inference_create_chat_completion_mcp.yml' + - $ref: 'examples/go/inference_create_chat_completion_vlm.yml' + - $ref: 'examples/go/inference_create_chat_completion_kb.yml' - $ref: 'examples/dots/inference_create_chat_completion.yml' security: - inference_bearer_auth: [] diff --git a/specification/resources/inference/inference_create_response.yml b/specification/resources/inference/inference_create_response.yml index 3250a5afd..ca3cc181a 100644 --- a/specification/resources/inference/inference_create_response.yml +++ b/specification/resources/inference/inference_create_response.yml @@ -43,6 +43,10 @@ x-codeSamples: - $ref: 'examples/curl/inference_create_response.yml' - $ref: 'examples/python/inference_create_response.yml' - $ref: 'examples/go/inference_create_response.yml' + - $ref: 'examples/go/inference_create_response_web_search.yml' + - $ref: 'examples/go/inference_create_response_web_fetch.yml' + - $ref: 'examples/go/inference_create_response_model_synthesis.yml' + - $ref: 'examples/go/inference_create_response_tool_search.yml' - $ref: 'examples/dots/inference_create_response.yml' security: - inference_bearer_auth: [] diff --git a/specification/resources/inference/inference_create_speech.yml b/specification/resources/inference/inference_create_speech.yml new file mode 100644 index 000000000..ff5de6366 --- /dev/null +++ b/specification/resources/inference/inference_create_speech.yml @@ -0,0 +1,59 @@ +operationId: inference_create_speech +summary: Generate speech from text +description: > + Convert text input to speech audio. The response may be raw audio bytes + (`audio/mpeg`, `audio/wav`, and similar) or a JSON envelope with + base64-encoded audio in `data[].b64_json`. +tags: + - Serverless Inference +servers: + - url: "https://inference.do-ai.run" + description: production +x-inference-base-url: "https://inference.do-ai.run" +requestBody: + required: true + content: + application/json: + schema: + $ref: "models/create_speech_request.yml" +responses: + "200": + description: Successful speech generation. + headers: + ratelimit-limit: + $ref: '../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../shared/headers.yml#/ratelimit-reset' + content: + application/json: + schema: + $ref: "models/speech_response.yml" + audio/mpeg: + schema: + type: string + format: binary + audio/wav: + schema: + type: string + format: binary + audio/mp3: + schema: + type: string + format: binary + "401": + $ref: '../../shared/responses/unauthorized.yml' + "429": + $ref: '../../shared/responses/too_many_requests.yml' + "500": + $ref: '../../shared/responses/server_error.yml' + default: + $ref: '../../shared/responses/unexpected_error.yml' +x-codeSamples: + - $ref: 'examples/curl/inference_create_speech.yml' + - $ref: 'examples/python/inference_create_speech.yml' + - $ref: 'examples/go/inference_create_speech.yml' + - $ref: 'examples/dots/inference_create_speech.yml' +security: + - inference_bearer_auth: [] diff --git a/specification/resources/inference/inference_create_video.yml b/specification/resources/inference/inference_create_video.yml new file mode 100644 index 000000000..1fa2036a3 --- /dev/null +++ b/specification/resources/inference/inference_create_video.yml @@ -0,0 +1,48 @@ +operationId: inference_create_video +summary: Start a video generation job +description: > + Start an asynchronous video generation job from a text prompt. Poll + `GET /v1/videos/{video_id}` until the job reaches a terminal status, then + download the MP4 with `GET /v1/videos/{video_id}/content` or from + `output.url` when present. +tags: + - Serverless Inference +servers: + - url: "https://inference.do-ai.run" + description: production +x-inference-base-url: "https://inference.do-ai.run" +requestBody: + required: true + content: + application/json: + schema: + $ref: "models/create_video_request.yml" +responses: + "200": + description: Video generation job accepted. + headers: + ratelimit-limit: + $ref: '../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../shared/headers.yml#/ratelimit-reset' + content: + application/json: + schema: + $ref: "models/video_generation.yml" + "401": + $ref: '../../shared/responses/unauthorized.yml' + "429": + $ref: '../../shared/responses/too_many_requests.yml' + "500": + $ref: '../../shared/responses/server_error.yml' + default: + $ref: '../../shared/responses/unexpected_error.yml' +x-codeSamples: + - $ref: 'examples/curl/inference_create_video.yml' + - $ref: 'examples/python/inference_create_video.yml' + - $ref: 'examples/go/inference_create_video.yml' + - $ref: 'examples/dots/inference_create_video.yml' +security: + - inference_bearer_auth: [] diff --git a/specification/resources/inference/inference_get_video.yml b/specification/resources/inference/inference_get_video.yml new file mode 100644 index 000000000..5efeca715 --- /dev/null +++ b/specification/resources/inference/inference_get_video.yml @@ -0,0 +1,50 @@ +operationId: inference_get_video +summary: Retrieve a video generation job +description: > + Returns the current state of a video generation job. Poll until `status` + reaches a terminal value such as `completed` or `failed`. +tags: + - Serverless Inference +servers: + - url: "https://inference.do-ai.run" + description: production +x-inference-base-url: "https://inference.do-ai.run" +parameters: + - in: path + name: video_id + description: The video generation job identifier. + required: true + schema: + type: string + example: "video_bGl0ZWxsbTpjdXN0b21fbGxtX3Byb3ZpZGVyOm9wZW5haTttb2RlbF9pZDo7dmlkZW9faWQ6ZGExYjFmYzMtYTM3NC00MmM0LTgxMWMtOWE5NmE3ZWY0OTIz" +responses: + "200": + description: The video generation job. + headers: + ratelimit-limit: + $ref: '../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../shared/headers.yml#/ratelimit-reset' + content: + application/json: + schema: + $ref: "models/video_generation.yml" + "401": + $ref: '../../shared/responses/unauthorized.yml' + "404": + $ref: '../../shared/responses/not_found.yml' + "429": + $ref: '../../shared/responses/too_many_requests.yml' + "500": + $ref: '../../shared/responses/server_error.yml' + default: + $ref: '../../shared/responses/unexpected_error.yml' +x-codeSamples: + - $ref: 'examples/curl/inference_get_video.yml' + - $ref: 'examples/python/inference_get_video.yml' + - $ref: 'examples/go/inference_get_video.yml' + - $ref: 'examples/dots/inference_get_video.yml' +security: + - inference_bearer_auth: [] diff --git a/specification/resources/inference/inference_get_video_content.yml b/specification/resources/inference/inference_get_video_content.yml new file mode 100644 index 000000000..c4f6ed300 --- /dev/null +++ b/specification/resources/inference/inference_get_video_content.yml @@ -0,0 +1,50 @@ +operationId: inference_get_video_content +summary: Download generated video content +description: > + Downloads the generated MP4 for a completed video generation job. +tags: + - Serverless Inference +servers: + - url: "https://inference.do-ai.run" + description: production +x-inference-base-url: "https://inference.do-ai.run" +parameters: + - in: path + name: video_id + description: The video generation job identifier. + required: true + schema: + type: string + example: "video_bGl0ZWxsbTpjdXN0b21fbGxtX3Byb3ZpZGVyOm9wZW5haTttb2RlbF9pZDo7dmlkZW9faWQ6ZGExYjFmYzMtYTM3NC00MmM0LTgxMWMtOWE5NmE3ZWY0OTIz" +responses: + "200": + description: Binary MP4 content. + headers: + ratelimit-limit: + $ref: '../../shared/headers.yml#/ratelimit-limit' + ratelimit-remaining: + $ref: '../../shared/headers.yml#/ratelimit-remaining' + ratelimit-reset: + $ref: '../../shared/headers.yml#/ratelimit-reset' + content: + video/mp4: + schema: + type: string + format: binary + "401": + $ref: '../../shared/responses/unauthorized.yml' + "404": + $ref: '../../shared/responses/not_found.yml' + "429": + $ref: '../../shared/responses/too_many_requests.yml' + "500": + $ref: '../../shared/responses/server_error.yml' + default: + $ref: '../../shared/responses/unexpected_error.yml' +x-codeSamples: + - $ref: 'examples/curl/inference_get_video_content.yml' + - $ref: 'examples/python/inference_get_video_content.yml' + - $ref: 'examples/go/inference_get_video_content.yml' + - $ref: 'examples/dots/inference_get_video_content.yml' +security: + - inference_bearer_auth: [] diff --git a/specification/resources/inference/models/create_speech_request.yml b/specification/resources/inference/models/create_speech_request.yml new file mode 100644 index 000000000..4e0f19e4f --- /dev/null +++ b/specification/resources/inference/models/create_speech_request.yml @@ -0,0 +1,29 @@ +type: object +description: Request body for text-to-speech generation. +required: + - model + - input +properties: + model: + type: string + description: The text-to-speech model to use. + example: "qwen3-tts-voicedesign" + input: + type: string + minLength: 1 + description: The text to convert to speech. + example: "Hello, world!" + voice: + type: string + description: The voice to use for synthesis. + example: "alloy" + response_format: + type: string + description: > + The audio format to return. Supported values include `mp3` and `wav`. + The API may return raw audio bytes or a JSON envelope with base64-encoded audio. + example: "mp3" + instructions: + type: string + description: Optional style or delivery instructions for the synthesizer. + example: "Speak naturally." diff --git a/specification/resources/inference/models/create_video_request.yml b/specification/resources/inference/models/create_video_request.yml new file mode 100644 index 000000000..1535badb5 --- /dev/null +++ b/specification/resources/inference/models/create_video_request.yml @@ -0,0 +1,24 @@ +type: object +description: Request body to start an asynchronous video generation job. +required: + - model + - prompt +properties: + model: + type: string + description: The video generation model to use. + example: "wan2-2-t2v-a14b" + prompt: + type: string + minLength: 1 + description: A text description of the desired video. + example: "Two anthropomorphic cats in boxing gear fight intensely on a spotlighted stage" + size: + type: string + description: The output resolution, for example `1280x720`. + example: "1280x720" + fps: + type: integer + minimum: 1 + description: Frames per second for the generated video. + example: 16 diff --git a/specification/resources/inference/models/speech_audio_item.yml b/specification/resources/inference/models/speech_audio_item.yml new file mode 100644 index 000000000..860e269e1 --- /dev/null +++ b/specification/resources/inference/models/speech_audio_item.yml @@ -0,0 +1,9 @@ +type: object +description: A single audio payload in a JSON speech response envelope. +required: + - b64_json +properties: + b64_json: + type: string + description: Base64-encoded audio bytes. + example: "//uQxAAAA..." diff --git a/specification/resources/inference/models/speech_response.yml b/specification/resources/inference/models/speech_response.yml new file mode 100644 index 000000000..28d6d9615 --- /dev/null +++ b/specification/resources/inference/models/speech_response.yml @@ -0,0 +1,17 @@ +type: object +description: > + JSON envelope for text-to-speech when the endpoint returns `application/json`. + The live endpoint may instead return raw audio bytes with an `audio/*` Content-Type. +required: + - data +properties: + created: + type: integer + description: Unix timestamp (in seconds) of when the audio was created. + example: 1710700000 + data: + type: array + minItems: 1 + description: Generated audio items. + items: + $ref: "speech_audio_item.yml" diff --git a/specification/resources/inference/models/video_generation.yml b/specification/resources/inference/models/video_generation.yml new file mode 100644 index 000000000..0f6e36eeb --- /dev/null +++ b/specification/resources/inference/models/video_generation.yml @@ -0,0 +1,40 @@ +type: object +description: Status of an asynchronous video generation job. +required: + - id + - status +properties: + id: + type: string + description: The video generation job identifier. + example: "video_bGl0ZWxsbTpjdXN0b21fbGxtX3Byb3ZpZGVyOm9wZW5haTttb2RlbF9pZDo7dmlkZW9faWQ6ZGExYjFmYzMtYTM3NC00MmM0LTgxMWMtOWE5NmE3ZWY0OTIz" + object: + type: string + description: Object type returned by the API. + example: "video" + created_at: + type: integer + description: Unix timestamp (in seconds) of when the job was created. + example: 1777003604 + model: + type: string + description: The model used for generation. + example: "wan2.2-t2v-a14b" + status: + type: string + description: > + Job status. Poll until the value is a terminal state such as `completed` or `failed`. + example: "processing" + output: + nullable: true + allOf: + - $ref: "video_generation_output.yml" + error: + type: object + nullable: true + description: Error details when status is `failed`. + additionalProperties: true + x_request_id: + type: string + nullable: true + description: Request correlation identifier when provided by the API. diff --git a/specification/resources/inference/models/video_generation_output.yml b/specification/resources/inference/models/video_generation_output.yml new file mode 100644 index 000000000..ecf51160d --- /dev/null +++ b/specification/resources/inference/models/video_generation_output.yml @@ -0,0 +1,8 @@ +type: object +description: Download location for a completed video when a presigned URL is available. +properties: + url: + type: string + format: uri + description: Presigned URL for the generated MP4. + example: "https://example.com/output.mp4"