SilkDock
API

Streaming

Stream tokens in real time via Server-Sent Events.

Add "stream": true to any chat request. Tokens are delivered as Server-Sent Events, ending with data: [DONE].


Examples

curl -X POST https://silkdock.ai/v1/chat/completions \-H "Authorization: Bearer $SILKDOCK_API_KEY" \-H "Content-Type: application/json" \--no-buffer \-d '{  "model": "gpt-4.1-mini",  "stream": true,  "messages": [{"role": "user", "content": "Write a short poem"}]}'
curl -X POST https://silkdock.ai/v1/chat/completions ^-H "Authorization: Bearer %SILKDOCK_API_KEY%" ^-H "Content-Type: application/json" ^--no-buffer ^-d "{"model":"gpt-4.1-mini","stream":true,"messages":[{"role":"user","content":"Write a short poem"}]}"
http --stream POST https://silkdock.ai/v1/chat/completions \Authorization:"Bearer $SILKDOCK_API_KEY" \model=gpt-4.1-mini \stream:=true \messages:='[{"role":"user","content":"Write a short poem"}]'
wget --no-buffer -q -O - \--method=POST \--header="Authorization: Bearer $SILKDOCK_API_KEY" \--header="Content-Type: application/json" \--body-data='{"model":"gpt-4.1-mini","stream":true,"messages":[{"role":"user","content":"Write a short poem"}]}' \https://silkdock.ai/v1/chat/completions
$headers = @{  "Authorization" = "Bearer $env:SILKDOCK_API_KEY"  "Content-Type"  = "application/json"}$body = '{"model":"gpt-4.1-mini","stream":true,"messages":[{"role":"user","content":"Write a short poem"}]}'$response = Invoke-RestMethod -Uri "https://silkdock.ai/v1/chat/completions" `  -Method POST `  -Headers $headers `  -Body $body `  -ResponseHeadersVariable respHeaders# For true streaming, use HttpClient directly$client = [System.Net.Http.HttpClient]::new()$client.DefaultRequestHeaders.Add("Authorization", "Bearer $env:SILKDOCK_API_KEY")$request = [System.Net.Http.HttpRequestMessage]::new("POST", "https://silkdock.ai/v1/chat/completions")$request.Content = [System.Net.Http.StringContent]::new($body, [System.Text.Encoding]::UTF8, "application/json")$responseMsg = $client.SendAsync($request, [System.Net.Http.HttpCompletionOption]::ResponseHeadersRead).Result$stream = $responseMsg.Content.ReadAsStreamAsync().Result$reader = [System.IO.StreamReader]::new($stream)while (-not $reader.EndOfStream) {  $line = $reader.ReadLine()  if ($line.StartsWith("data: ") -and $line -ne "data: [DONE]") {      Write-Host $line.Substring(6)  }}
const { OpenAI } = require("openai");const client = new OpenAI({apiKey: process.env.SILKDOCK_API_KEY,baseURL: "https://silkdock.ai/v1",});const stream = await client.chat.completions.create({model: "gpt-4.1-mini",messages: [{ role: "user", content: "Write a short poem" }],stream: true,});for await (const chunk of stream) {const content = chunk.choices[0]?.delta?.content || "";process.stdout.write(content);}
const res = await fetch("https://silkdock.ai/v1/chat/completions", {method: "POST",headers: {  "Authorization": `Bearer ${process.env.SILKDOCK_API_KEY}`,  "Content-Type": "application/json",},body: JSON.stringify({  model: "gpt-4.1-mini",  action: "chat",  stream: true,  messages: [{ role: "user", content: "Write a short poem" }],}),});const reader = res.body.getReader();const decoder = new TextDecoder();while (true) {const { done, value } = await reader.read();if (done) break;for (const line of decoder.decode(value).split("\n")) {  if (!line.startsWith("data: ") || line === "data: [DONE]") continue;  const chunk = JSON.parse(line.slice(6));  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");}}
const axios = require("axios");const response = await axios.post("https://silkdock.ai/v1/chat/completions",{  model: "gpt-4.1-mini",  action: "chat",  stream: true,  messages: [{ role: "user", content: "Write a short poem" }],},{  headers: {    Authorization: `Bearer ${process.env.SILKDOCK_API_KEY}`,    "Content-Type": "application/json",  },  responseType: "stream",});response.data.on("data", (chunk) => {const lines = chunk.toString().split("\n");for (const line of lines) {  if (!line.startsWith("data: ") || line === "data: [DONE]") continue;  const data = JSON.parse(line.slice(6));  process.stdout.write(data.choices[0]?.delta?.content ?? "");}});
// jQuery does not natively support SSE streaming.// Use XHR directly or the EventSource API for true streaming.// The example below collects the full response on completion.$.ajax({url: "https://silkdock.ai/v1/chat/completions",type: "POST",contentType: "application/json",headers: {  Authorization: `Bearer ${SILKDOCK_API_KEY}`,},data: JSON.stringify({  model: "gpt-4.1-mini",  action: "chat",  stream: true,  messages: [{ role: "user", content: "Write a short poem" }],}),xhrFields: {  onprogress: function () {    const raw = this.responseText;    const lines = raw.split("\n");    for (const line of lines) {      if (!line.startsWith("data: ") || line === "data: [DONE]") continue;      const chunk = JSON.parse(line.slice(6));      console.log(chunk.choices[0]?.delta?.content ?? "");    }  },},});
const xhr = new XMLHttpRequest();xhr.open("POST", "https://silkdock.ai/v1/chat/completions", true);xhr.setRequestHeader("Authorization", `Bearer ${SILKDOCK_API_KEY}`);xhr.setRequestHeader("Content-Type", "application/json");let cursor = 0;xhr.onprogress = function () {const newText = xhr.responseText.slice(cursor);cursor = xhr.responseText.length;for (const line of newText.split("\n")) {  if (!line.startsWith("data: ") || line === "data: [DONE]") continue;  const chunk = JSON.parse(line.slice(6));  console.log(chunk.choices[0]?.delta?.content ?? "");}};xhr.send(JSON.stringify({model: "gpt-4.1-mini",action: "chat",stream: true,messages: [{ role: "user", content: "Write a short poem" }],}));
// 'request' package – receives streamed chunks as they arriveconst request = require("request");request.post({url: "https://silkdock.ai/v1/chat/completions",headers: {  Authorization: `Bearer ${process.env.SILKDOCK_API_KEY}`,  "Content-Type": "application/json",},body: JSON.stringify({  model: "gpt-4.1-mini",  action: "chat",  stream: true,  messages: [{ role: "user", content: "Write a short poem" }],}),}).on("data", (chunk) => {  const lines = chunk.toString().split("\n");  for (const line of lines) {    if (!line.startsWith("data: ") || line === "data: [DONE]") continue;    const data = JSON.parse(line.slice(6));    process.stdout.write(data.choices[0]?.delta?.content ?? "");  }}).on("end", () => console.log("\n[done]"));
const unirest = require("unirest");// unirest streams through the underlying 'request' moduleunirest.post("https://silkdock.ai/v1/chat/completions").header("Authorization", `Bearer ${process.env.SILKDOCK_API_KEY}`).header("Content-Type", "application/json").send(  JSON.stringify({    model: "gpt-4.1-mini",    action: "chat",    stream: true,    messages: [{ role: "user", content: "Write a short poem" }],  })).pipe(  (() => {    const { Writable } = require("stream");    return new Writable({      write(chunk, _enc, cb) {        const lines = chunk.toString().split("\n");        for (const line of lines) {          if (!line.startsWith("data: ") || line === "data: [DONE]") continue;          const data = JSON.parse(line.slice(6));          process.stdout.write(data.choices[0]?.delta?.content ?? "");        }        cb();      },    });  })());
import OpenAI from "openai";const client = new OpenAI({apiKey: process.env.SILKDOCK_API_KEY,baseURL: "https://silkdock.ai/v1",});const stream = await client.chat.completions.create({model: "gpt-4.1-mini",messages: [{ role: "user", content: "Write a short poem" }],stream: true,});for await (const chunk of stream) {const content = chunk.choices[0]?.delta?.content ?? "";process.stdout.write(content);}
const res = await fetch("https://silkdock.ai/v1/chat/completions", {method: "POST",headers: {  "Authorization": `Bearer ${process.env.SILKDOCK_API_KEY}`,  "Content-Type": "application/json",},body: JSON.stringify({  model: "gpt-4.1-mini",  action: "chat",  stream: true,  messages: [{ role: "user", content: "Write a short poem" }],}),});const reader = res.body!.getReader();const decoder = new TextDecoder();while (true) {const { done, value } = await reader.read();if (done) break;for (const line of decoder.decode(value).split("\n")) {  if (!line.startsWith("data: ") || line === "data: [DONE]") continue;  const chunk = JSON.parse(line.slice(6));  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");}}
import requests, json, oswith requests.post(  "https://silkdock.ai/v1/chat/completions",  headers={"Authorization": f"Bearer {os.getenv('SILKDOCK_API_KEY')}"},  json={      "model": "gpt-4.1-mini",      "stream": True,      "messages": [{"role": "user", "content": "Write a short poem"}],  },  stream=True,) as res:  for line in res.iter_lines():      if not line or line == b"data: [DONE]":          continue      chunk = json.loads(line.removeprefix(b"data: "))      print(chunk["choices"][0]["delta"].get("content", ""), end="", flush=True)
import osfrom openai import OpenAIclient = OpenAI(  api_key=os.getenv("SILKDOCK_API_KEY"),  base_url="https://silkdock.ai/v1")stream = client.chat.completions.create(  model="gpt-4.1-mini",  messages=[{"role": "user", "content": "Write a short poem"}],  stream=True)for chunk in stream:  delta = chunk.choices[0].delta  if delta.content:      print(delta.content, end="", flush=True)
#include <stdio.h>#include <string.h>#include <curl/curl.h>static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {  size_t total = size * nmemb;  /* ptr may contain multiple lines separated by \n */  char buf[8192];  memcpy(buf, ptr, total < sizeof(buf) - 1 ? total : sizeof(buf) - 1);  buf[total < sizeof(buf) - 1 ? total : sizeof(buf) - 1] = '\0';  char *line = strtok(buf, "\n");  while (line) {      if (strncmp(line, "data: ", 6) == 0 && strcmp(line, "data: [DONE]") != 0) {          printf("%s\n", line + 6);          fflush(stdout);      }      line = strtok(NULL, "\n");  }  return total;}int main(void) {  CURL *curl = curl_easy_init();  if (!curl) return 1;  const char *api_key = getenv("SILKDOCK_API_KEY");  char auth_header[256];  snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", api_key ? api_key : "");  struct curl_slist *headers = NULL;  headers = curl_slist_append(headers, auth_header);  headers = curl_slist_append(headers, "Content-Type: application/json");  const char *body =      "{\"model\":\"gpt-4.1-mini\",\"stream\":true,"      "\"messages\":[{\"role\":\"user\",\"content\":\"Write a short poem\"}]}";  curl_easy_setopt(curl, CURLOPT_URL, "https://silkdock.ai/v1/chat/completions");  curl_easy_setopt(curl, CURLOPT_POST, 1L);  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);  curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);  curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 1L); /* minimize buffering */  curl_easy_perform(curl);  curl_slist_free_all(headers);  curl_easy_cleanup(curl);  return 0;}
#import <Foundation/Foundation.h>@interface StreamDelegate : NSObject <NSURLSessionDataDelegate>@property (nonatomic, strong) NSMutableData *buffer;@end@implementation StreamDelegate- (instancetype)init {  self = [super init];  _buffer = [NSMutableData data];  return self;}- (void)URLSession:(NSURLSession *)session        dataTask:(NSURLSessionDataTask *)dataTask  didReceiveData:(NSData *)data {  [self.buffer appendData:data];  // Process complete lines  NSString *text = [[NSString alloc] initWithData:self.buffer encoding:NSUTF8StringEncoding];  NSArray<NSString *> *lines = [text componentsSeparatedByString:@"\n"];  NSMutableData *remainder = [NSMutableData data];  for (NSUInteger i = 0; i < lines.count; i++) {      NSString *line = lines[i];      if (i == lines.count - 1) {          // Last segment may be incomplete          [remainder appendData:[line dataUsingEncoding:NSUTF8StringEncoding]];          break;      }      if ([line hasPrefix:@"data: "] && ![line isEqualToString:@"data: [DONE]"]) {          NSString *json = [line substringFromIndex:6];          NSLog(@"%@", json);      }  }  self.buffer = remainder;}- (void)URLSession:(NSURLSession *)session            task:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)error {  if (error) NSLog(@"Error: %@", error);  CFRunLoopStop(CFRunLoopGetMain());}@endint main(int argc, const char *argv[]) {  @autoreleasepool {      NSURL *url = [NSURL URLWithString:@"https://silkdock.ai/v1/chat/completions"];      NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];      req.HTTPMethod = @"POST";      NSString *apiKey = [NSProcessInfo.processInfo.environment objectForKey:@"SILKDOCK_API_KEY"];      [req setValue:[NSString stringWithFormat:@"Bearer %@", apiKey] forHTTPHeaderField:@"Authorization"];      [req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];      NSDictionary *bodyDict = @{          @"model": @"gpt-4.1-mini",          @"stream": @YES,          @"messages": @[@{@"role": @"user", @"content": @"Write a short poem"}],      };      req.HTTPBody = [NSJSONSerialization dataWithJSONObject:bodyDict options:0 error:nil];      StreamDelegate *delegate = [[StreamDelegate alloc] init];      NSURLSession *session = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration                                                            delegate:delegate                                                       delegateQueue:nil];      [[session dataTaskWithRequest:req] resume];      CFRunLoopRun();  }  return 0;}
import com.openai.client.OpenAIClient;import com.openai.client.okhttp.OpenAIOkHttpClient;import com.openai.models.*;OpenAIClient client = OpenAIOkHttpClient.builder()  .apiKey(System.getenv("SILKDOCK_API_KEY"))  .baseURL("https://silkdock.ai/v1")  .build();client.chat().completions().createStreaming(  ChatCompletionCreateParams.builder()      .model(ChatModel.GPT_4_1_MINI)      .addUserMessage("Write a short poem")      .build()).subscribe(chunk ->  chunk.choices().stream()      .map(c -> c.delta().content().orElse(""))      .forEach(System.out::print));
import java.net.http.*;import java.net.URI;import java.io.*;var req = HttpRequest.newBuilder()  .uri(URI.create("https://silkdock.ai/v1/chat/completions"))  .header("Authorization", "Bearer " + System.getenv("SILKDOCK_API_KEY"))  .header("Content-Type", "application/json")  .POST(HttpRequest.BodyPublishers.ofString(      """{"model":"gpt-4.1-mini","stream":true,         "messages":[{"role":"user","content":"Write a short poem"}]}"""))  .build();HttpClient.newHttpClient()  .send(req, HttpResponse.BodyHandlers.ofLines())  .body()  .filter(line -> line.startsWith("data: ") && !line.equals("data: [DONE]"))  .map(line -> line.substring(6))  .forEach(System.out::println);
import okhttp3.*;import java.io.*;OkHttpClient client = new OkHttpClient();String body = "{\"model\":\"gpt-4.1-mini\",\"stream\":true," +            "\"messages\":[{\"role\":\"user\",\"content\":\"Write a short poem\"}]}";Request request = new Request.Builder()  .url("https://silkdock.ai/v1/chat/completions")  .addHeader("Authorization", "Bearer " + System.getenv("SILKDOCK_API_KEY"))  .addHeader("Content-Type", "application/json")  .post(RequestBody.create(body, MediaType.parse("application/json")))  .build();try (Response response = client.newCall(request).execute()) {  if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);  BufferedReader reader = new BufferedReader(response.body().charStream());  String line;  while ((line = reader.readLine()) != null) {      if (line.startsWith("data: ") && !line.equals("data: [DONE]")) {          System.out.println(line.substring(6));      }  }}
// Unirest does not natively support SSE streaming.// The example below collects the full response body on completion.import kong.unirest.*;HttpResponse<String> response = Unirest.post("https://silkdock.ai/v1/chat/completions")  .header("Authorization", "Bearer " + System.getenv("SILKDOCK_API_KEY"))  .header("Content-Type", "application/json")  .body("{\"model\":\"gpt-4.1-mini\",\"stream\":true," +        "\"messages\":[{\"role\":\"user\",\"content\":\"Write a short poem\"}]}")  .asString();for (String line : response.getBody().split("\n")) {  if (line.startsWith("data: ") && !line.equals("data: [DONE]")) {      System.out.println(line.substring(6));  }}
package mainimport (  "context"  "fmt"  "os"  "github.com/openai/openai-go"  "github.com/openai/openai-go/option")func main() {  client := openai.NewClient(      option.WithAPIKey(os.Getenv("SILKDOCK_API_KEY")),      option.WithBaseURL("https://silkdock.ai/v1"),  )  stream := client.Chat.Completions.NewStreaming(context.Background(),      openai.ChatCompletionNewParams{          Model: openai.F(openai.ChatModelGPT4_1Mini),          Messages: openai.F([]openai.ChatCompletionMessageParamUnion{              openai.UserMessage("Write a short poem"),          }),      },  )  for stream.Next() {      chunk := stream.Current()      if len(chunk.Choices) > 0 {          fmt.Print(chunk.Choices[0].Delta.Content)      }  }}
package mainimport (  "bufio"  "bytes"  "encoding/json"  "fmt"  "net/http"  "os"  "strings")func main() {  body, _ := json.Marshal(map[string]any{      "model": "gpt-4.1-mini", "stream": true,      "messages": []map[string]string{{"role": "user", "content": "Write a short poem"}},  })  req, _ := http.NewRequest("POST", "https://silkdock.ai/v1/chat/completions", bytes.NewReader(body))  req.Header.Set("Authorization", "Bearer "+os.Getenv("SILKDOCK_API_KEY"))  req.Header.Set("Content-Type", "application/json")  resp, _ := http.DefaultClient.Do(req)  defer resp.Body.Close()  scanner := bufio.NewScanner(resp.Body)  for scanner.Scan() {      line := scanner.Text()      if !strings.HasPrefix(line, "data: ") || line == "data: [DONE]" {          continue      }      var chunk map[string]any      json.Unmarshal([]byte(line[6:]), &chunk)      fmt.Print(chunk)  }}
<?php$ch = curl_init("https://silkdock.ai/v1/chat/completions");curl_setopt_array($ch, [  CURLOPT_POST           => true,  CURLOPT_RETURNTRANSFER => false,  CURLOPT_HTTPHEADER     => [      "Authorization: Bearer " . getenv("SILKDOCK_API_KEY"),      "Content-Type: application/json",  ],  CURLOPT_POSTFIELDS => json_encode([      "model"    => "gpt-4.1-mini",              "stream"   => true,      "messages" => [["role" => "user", "content" => "Write a short poem"]],  ]),  CURLOPT_WRITEFUNCTION => function($ch, $data) {      echo $data;      flush();      return strlen($data);  },]);curl_exec($ch);
<?php// HTTP_Request2 does not stream responses natively.// Install via: composer require pear/http_request2require_once "vendor/autoload.php";use HTTP_Request2;$request = new HTTP_Request2("https://silkdock.ai/v1/chat/completions", HTTP_Request2::METHOD_POST);$request->setHeader("Authorization", "Bearer " . getenv("SILKDOCK_API_KEY"));$request->setHeader("Content-Type", "application/json");$request->setBody(json_encode([  "model"    => "gpt-4.1-mini",      "stream"   => true,  "messages" => [["role" => "user", "content" => "Write a short poem"]],]));$response = $request->send();$body = $response->getBody();foreach (explode("\n", $body) as $line) {  if (str_starts_with($line, "data: ") && $line !== "data: [DONE]") {      echo substr($line, 6) . "\n";      flush();  }}
<?php// Install via: composer require guzzlehttp/guzzlerequire_once "vendor/autoload.php";use GuzzleHttp\Client;$client = new Client();$response = $client->post("https://silkdock.ai/v1/chat/completions", [  "headers" => [      "Authorization" => "Bearer " . getenv("SILKDOCK_API_KEY"),      "Content-Type"  => "application/json",  ],  "json" => [      "model"    => "gpt-4.1-mini",              "stream"   => true,      "messages" => [["role" => "user", "content" => "Write a short poem"]],  ],  "stream" => true,]);$body = $response->getBody();$buffer = "";while (!$body->eof()) {  $buffer .= $body->read(1024);  $lines = explode("\n", $buffer);  // Keep last (possibly incomplete) line in the buffer  $buffer = array_pop($lines);  foreach ($lines as $line) {      if (str_starts_with($line, "data: ") && $line !== "data: [DONE]") {          echo substr($line, 6) . "\n";          flush();      }  }}
<?php// Requires the pecl_http (http) extension: pecl install pecl_http$client = new http\Client();$request = new http\Client\Request(  "POST",  "https://silkdock.ai/v1/chat/completions",  [      "Authorization" => "Bearer " . getenv("SILKDOCK_API_KEY"),      "Content-Type"  => "application/json",  ],  new http\Message\Body(      fopen("data://text/plain," . urlencode(json_encode([          "model"    => "gpt-4.1-mini",                      "stream"   => true,          "messages" => [["role" => "user", "content" => "Write a short poem"]],      ])), "r")  ));$client->enqueue($request)->send();$response = $client->getResponse();$body = $response->getBody();foreach (explode("\n", (string)$body) as $line) {  if (str_starts_with($line, "data: ") && $line !== "data: [DONE]") {      echo substr($line, 6) . "\n";      flush();  }}
import OpenAIlet client = OpenAI(configuration: .init(  token: ProcessInfo.processInfo.environment["SILKDOCK_API_KEY"]!,  host: "silkdock.ai",  scheme: "https"))let query = ChatQuery(  messages: [.init(role: .user, content: "Write a short poem")],  model: "gpt-4.1-mini")for try await result in client.chatsStream(query: query) {  print(result.choices.first?.delta.content ?? "", terminator: "")}
import Foundationvar req = URLRequest(url: URL(string: "https://silkdock.ai/v1/chat/completions")!)req.httpMethod = "POST"req.setValue("Bearer \(ProcessInfo.processInfo.environment["SILKDOCK_API_KEY"]!)",           forHTTPHeaderField: "Authorization")req.setValue("application/json", forHTTPHeaderField: "Content-Type")req.httpBody = try! JSONSerialization.data(withJSONObject: [  "model": "gpt-4.1-mini", "stream": true,  "messages": [["role": "user", "content": "Write a short poem"]],])let (stream, _) = try! await URLSession.shared.bytes(for: req)for try await line in stream.lines {  guard line.hasPrefix("data: "), line != "data: [DONE]" else { continue }  print(line.dropFirst(6))}
using OpenAI;using OpenAI.Chat;var client = new ChatClient(  model: "gpt-4.1-mini",  credential: new System.ClientModel.ApiKeyCredential(      Environment.GetEnvironmentVariable("SILKDOCK_API_KEY")!),  options: new OpenAIClientOptions {      Endpoint = new Uri("https://silkdock.ai/v1")  });await foreach (var update in client.CompleteChatStreamingAsync(  new UserChatMessage("Write a short poem"))){  foreach (var part in update.ContentUpdate)      Console.Write(part.Text);}
using System.Net.Http;using System.Net.Http.Json;var client = new HttpClient();client.DefaultRequestHeaders.Add("Authorization",  $"Bearer {Environment.GetEnvironmentVariable("SILKDOCK_API_KEY")}");var res = await client.PostAsJsonAsync("https://silkdock.ai/v1/chat/completions", new {  model = "gpt-4.1-mini", stream = true,  messages = new[] { new { role = "user", content = "Write a short poem" } },});using var reader = new StreamReader(await res.Content.ReadAsStreamAsync());while (!reader.EndOfStream) {  var line = await reader.ReadLineAsync();  if (line?.StartsWith("data: ") == true && line != "data: [DONE]")      Console.WriteLine(line[6..]);}
require "openai"client = OpenAI::Client.new(access_token: ENV["SILKDOCK_API_KEY"],uri_base: "https://silkdock.ai/v1")client.chat(parameters: {  model: "gpt-4.1-mini",  messages: [{ role: "user", content: "Write a short poem" }],  stream: proc { |chunk, _bytesize|    print chunk.dig("choices", 0, "delta", "content")  }})
require "net/http"require "json"uri = URI("https://silkdock.ai/v1/chat/completions")req = Net::HTTP::Post.new(uri)req["Authorization"] = "Bearer #{ENV['SILKDOCK_API_KEY']}"req["Content-Type"]  = "application/json"req.body = {model: "gpt-4.1-mini", stream: true,messages: [{ role: "user", content: "Write a short poem" }]}.to_jsonNet::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|http.request(req) do |res|  res.read_body do |chunk|    chunk.each_line do |line|      next unless line.start_with?("data: ") && line.strip != "data: [DONE]"      puts line[6..]    end  endendend
import com.openai.client.OpenAIClientimport com.openai.client.okhttp.OpenAIOkHttpClientimport com.openai.models.*val client: OpenAIClient = OpenAIOkHttpClient.builder()  .apiKey(System.getenv("SILKDOCK_API_KEY"))  .baseURL("https://silkdock.ai/v1")  .build()client.chat().completions().createStreaming(  ChatCompletionCreateParams.builder()      .model(ChatModel.GPT_4_1_MINI)      .addUserMessage("Write a short poem")      .build()).subscribe { chunk ->  chunk.choices().forEach { choice ->      print(choice.delta().content().orElse(""))  }}
import java.net.http.*import java.net.URIval req = HttpRequest.newBuilder()  .uri(URI.create("https://silkdock.ai/v1/chat/completions"))  .header("Authorization", "Bearer ${System.getenv("SILKDOCK_API_KEY")}")  .header("Content-Type", "application/json")  .POST(HttpRequest.BodyPublishers.ofString(      """{"model":"gpt-4.1-mini","stream":true,         "messages":[{"role":"user","content":"Write a short poem"}]}"""))  .build()HttpClient.newHttpClient()  .send(req, HttpResponse.BodyHandlers.ofLines())  .body()  .filter { it.startsWith("data: ") && it != "data: [DONE]" }  .forEach { println(it.substring(6)) }
use reqwest::blocking::Client;use serde_json::json;use std::io::{BufRead, BufReader};fn main() -> Result<(), Box<dyn std::error::Error>> {  let res = Client::new()      .post("https://silkdock.ai/v1/chat/completions")      .header("Authorization", format!("Bearer {}", std::env::var("SILKDOCK_API_KEY")?))      .json(&json!({          "model": "gpt-4.1-mini", "stream": true,          "messages": [{"role": "user", "content": "Write a short poem"}]      }))      .send()?;  for line in BufReader::new(res).lines().flatten() {      if line.starts_with("data: ") && line != "data: [DONE]" {          println!("{}", &line[6..]);      }  }  Ok(())}
POST /v1/chat/completions HTTP/1.1Host: silkdock.aiAuthorization: Bearer <YOUR_API_KEY>Content-Type: application/json{"model": "gpt-4.1-mini","stream": true,"messages": [{"role": "user", "content": "Write a short poem"}]}
import 'dart:convert';import 'package:http/http.dart' as http;void main() async {final req = http.Request('POST', Uri.parse('https://silkdock.ai/v1/chat/completions'))  ..headers['Authorization'] = 'Bearer ${const String.fromEnvironment("SILKDOCK_API_KEY")}'  ..headers['Content-Type'] = 'application/json'  ..body = jsonEncode({    'model': 'gpt-4.1-mini', 'action': 'chat', 'stream': true,    'messages': [{'role': 'user', 'content': 'Write a short poem'}],  });final res = await http.Client().send(req);await for (final chunk in res.stream.transform(utf8.decoder).transform(const LineSplitter())) {  if (chunk.startsWith('data: ') && chunk != 'data: [DONE]') {    print(chunk.substring(6));  }}}
library(httr2)req <- request("https://silkdock.ai/v1/chat/completions") |>req_headers(  Authorization = paste("Bearer", Sys.getenv("SILKDOCK_API_KEY")),  "Content-Type" = "application/json") |>req_body_json(list(  model    = "gpt-4.1-mini",  action   = "chat",  stream   = TRUE,  messages = list(list(role = "user", content = "Write a short poem"))))# Stream response line by lineresp <- req_perform_connection(req)while (!is.null(line <- readLines(resp, n = 1, warn = FALSE))) {if (startsWith(line, "data: ") && line != "data: [DONE]")  cat(substring(line, 7), "\n")}
(* requires cohttp-lwt-unix: opam install cohttp-lwt-unix *)open Cohttp_lwt_unixopen Cohttpopen Lwtlet () =let body =  {|{"model":"gpt-4.1-mini","stream":true,  "messages":[{"role":"user","content":"Write a short poem"}]}|}inlet headers =  Header.of_list    [ ("Authorization", "Bearer " ^ Sys.getenv "SILKDOCK_API_KEY")    ; ("Content-Type", "application/json")    ]inLwt_main.run  ( Client.post ~headers      ~body:(Cohttp_lwt.Body.of_string body)      (Uri.of_string "https://silkdock.ai/v1/chat/completions")  >>= fun (_, body) ->    Cohttp_lwt.Body.to_string body  >>= fun s ->    String.split_on_char '\n' s    |> List.iter (fun line ->           if String.length line > 6 && String.sub line 0 6 = "data: "           then             print_string               (String.sub line 6 (String.length line - 6)));    return_unit )

Chunk format

Each event is a data: line containing a JSON object:

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion.chunk",
  "model": "gpt-4.1-mini",
  "choices": [
    {
      "index": 0,
      "delta": { "content": "Roses" },
      "finish_reason": null
    }
  ]
}

The final chunk has "finish_reason": "stop", followed by data: [DONE].

Last updated on

On this page