Signed URL¶
Generate a fresh time-limited signed URL for a result asset of one of your models, for example the annotated image returned as yolo_result_path by a prediction. Use it when the link that came back with the prediction has expired.
The request is authenticated with the model's API key, and a key can only obtain links for result files of its own model. The signed URL itself needs no further authentication, so treat it like a password for that one file and keep its lifetime short.
POST /inference/assets/signed-url¶
Request¶
Content-Type: application/json
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
api_key |
string |
Yes | — | API key of the model that produced the result |
object_path |
string |
Yes | — | The yolo_result_path returned by a prediction (always <job_id>/result/<file> for that model) |
expires_in |
integer |
No | 3600 |
URL expiry time in seconds. Clamped to 60 – 86400 (24 hours) |
{
"api_key": "YOUR_MODEL_API_KEY",
"object_path": "<job_id>/result/photo_yolo_result.png",
"expires_in": 3600
}
Response¶
| Field | Type | Description |
|---|---|---|
object_path |
string |
The original object path |
signed_url |
string |
The temporary signed URL to access the asset |
expires_in |
integer |
Expiry duration in seconds |
{
"object_path": "<job_id>/result/photo_yolo_result.png",
"signed_url": "https://storage.example.com/<job_id>/result/photo_yolo_result.png?signature=...",
"expires_in": 3600
}
Errors¶
| Status | When |
|---|---|
401 |
api_key is missing, empty, unknown, revoked or expired |
403 |
The key may not make predictions, or object_path is not a result file of that key's model (another model's file, a dataset, model weights, or a path containing ..) |
422 |
The request body is malformed, for example api_key is absent |
URL expiry
Signed URLs are valid only for the expires_in period. Request a new URL before expiry if you need continued access.
Code Examples¶
async function getSignedUrl(apiKey, objectPath, expiresIn = 3600) {
const response = await fetch(
"https://sightapi.raku.so/inference/assets/signed-url",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ api_key: apiKey, object_path: objectPath, expires_in: expiresIn }),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail?.message ?? "Request failed");
}
return response.json();
}
// Usage
const { signed_url } = await getSignedUrl(API_KEY, "<job_id>/result/photo_yolo_result.png");
console.log("Download URL:", signed_url);
// Fetch the asset
const asset = await fetch(signed_url);
const data = await asset.json();
interface SignedUrlResponse {
object_path: string;
signed_url: string;
expires_in: number;
}
async function getSignedUrl(
apiKey: string,
objectPath: string,
expiresIn: number = 3600
): Promise<SignedUrlResponse> {
const response = await fetch(
"https://sightapi.raku.so/inference/assets/signed-url",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ api_key: apiKey, object_path: objectPath, expires_in: expiresIn }),
}
);
if (!response.ok) {
const error = await response.json();
throw new Error((error.detail as { message: string })?.message ?? "Request failed");
}
return response.json() as Promise<SignedUrlResponse>;
}
// Usage
const { signed_url } = await getSignedUrl(API_KEY, "<job_id>/result/photo_yolo_result.png");
console.log("Download URL:", signed_url);
import httpx
from dataclasses import dataclass
@dataclass
class SignedUrlResponse:
object_path: str
signed_url: str
expires_in: int
def get_signed_url(api_key: str, object_path: str, expires_in: int = 3600) -> SignedUrlResponse:
with httpx.Client() as client:
response = client.post(
"https://sightapi.raku.so/inference/assets/signed-url",
json={"api_key": api_key, "object_path": object_path, "expires_in": expires_in},
)
response.raise_for_status()
data = response.json()
return SignedUrlResponse(**data)
# Usage
result = get_signed_url(API_KEY, "<job_id>/result/photo_yolo_result.png")
print("Download URL:", result.signed_url)
# Fetch the asset
with httpx.Client() as client:
asset = client.get(result.signed_url)
print(asset.json())
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
public record SignedUrlResponse(
[property: JsonPropertyName("object_path")] string ObjectPath,
[property: JsonPropertyName("signed_url")] string SignedUrl,
[property: JsonPropertyName("expires_in")] int ExpiresIn);
public class RakuSightClient
{
private static readonly HttpClient Http = new();
public static async Task<SignedUrlResponse> GetSignedUrlAsync(
string apiKey, string objectPath, int expiresIn = 3600)
{
var payload = new { api_key = apiKey, object_path = objectPath, expires_in = expiresIn };
var response = await Http.PostAsJsonAsync(
"https://sightapi.raku.so/inference/assets/signed-url",
payload);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<SignedUrlResponse>()
?? throw new InvalidOperationException("Empty response");
}
}
// Usage
var result = await RakuSightClient.GetSignedUrlAsync(apiKey, "<job_id>/result/photo_yolo_result.png");
Console.WriteLine($"Download URL: {result.SignedUrl}");
// Fetch the asset via the signed URL
var asset = await new HttpClient().GetStringAsync(result.SignedUrl);
Console.WriteLine(asset);
import java.net.http.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class RakuSightClient {
private static final HttpClient CLIENT = HttpClient.newHttpClient();
private static final ObjectMapper MAPPER = new ObjectMapper();
public static JsonNode getSignedUrl(String apiKey, String objectPath, int expiresIn) throws Exception {
String body = String.format(
"{\"api_key\":\"%s\",\"object_path\":\"%s\",\"expires_in\":%d}",
apiKey, objectPath, expiresIn
);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://sightapi.raku.so/inference/assets/signed-url"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
.build();
HttpResponse<String> response = CLIENT.send(
request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new RuntimeException("Request failed: " + response.body());
}
return MAPPER.readTree(response.body());
}
public static void main(String[] args) throws Exception {
JsonNode result = getSignedUrl(apiKey, "<job_id>/result/photo_yolo_result.png", 3600);
String signedUrl = result.get("signed_url").asText();
System.out.println("Download URL: " + signedUrl);
// Fetch the asset
HttpRequest assetRequest = HttpRequest.newBuilder()
.uri(URI.create(signedUrl))
.GET()
.build();
HttpResponse<String> asset = CLIENT.send(
assetRequest, HttpResponse.BodyHandlers.ofString());
System.out.println(asset.body());
}
}
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type SignedUrlRequest struct {
APIKey string `json:"api_key"`
ObjectPath string `json:"object_path"`
ExpiresIn int `json:"expires_in"`
}
type SignedUrlResponse struct {
ObjectPath string `json:"object_path"`
SignedURL string `json:"signed_url"`
ExpiresIn int `json:"expires_in"`
}
func getSignedUrl(apiKey, objectPath string, expiresIn int) (*SignedUrlResponse, error) {
if expiresIn == 0 {
expiresIn = 3600
}
payload, _ := json.Marshal(SignedUrlRequest{
APIKey: apiKey,
ObjectPath: objectPath,
ExpiresIn: expiresIn,
})
resp, err := http.Post(
"https://sightapi.raku.so/inference/assets/signed-url",
"application/json",
bytes.NewReader(payload),
)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var result SignedUrlResponse
json.NewDecoder(resp.Body).Decode(&result)
return &result, nil
}
func main() {
result, err := getSignedUrl(apiKey, "<job_id>/result/photo_yolo_result.png", 3600)
if err != nil {
panic(err)
}
fmt.Println("Download URL:", result.SignedURL)
// Fetch the asset via signed URL
assetResp, _ := http.Get(result.SignedURL)
defer assetResp.Body.Close()
var asset map[string]any
json.NewDecoder(assetResp.Body).Decode(&asset)
fmt.Println(asset)
}