Start here
Signed URLs for what a job produced
/v1/jobs/{id}/assetson https://api.auray.ai/v1Signs and does not proxy: fetch the URLs directly.
Signs and does not proxy: fetch the URLs directly. They live fifteen minutes, which is what makes soft delete real, and never past the files themselves, which are deleted three days after the job was made: a link signed in a job's last minutes dies with its file. Once a job is past its three days this answers 410 expired with reason: retention_ended until the retention sweep removes the job, normally within minutes, and 404 not_found after that. Spends the egress bucket in whole megabytes when it signs, not when a link is fetched: a signed link can be fetched again until it expires, and asking for the links again spends the bucket again.
#Authentication
Authorization: Bearer auray_sk_… — assets:read. Signing is metered as egress, once per call; fetching a signed link is not counted.
#Request
#Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | yes |
#Example request
curl https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets \
-H "Authorization: Bearer $AURAY_API_KEY"import { createClient } from "@auray/client";
const auray = createClient(); // reads AURAY_API_KEY
const { assets } = await auray.platform.jobs.assets("photo_docs-mtpb1vnh");
for (const asset of assets) console.log(asset.url);from auray_client import Client
auray = Client() # reads AURAY_API_KEY
listing = auray.platform.jobs.assets("photo_docs-mtpb1vnh")
for asset in listing["assets"]:
print(asset["url"])const res = await fetch("https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.AURAY_API_KEY}` },
});
console.log(await res.json());import os, requests
r = requests.get(
"https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets",
headers={"Authorization": f"Bearer {os.environ['AURAY_API_KEY']}"},
)
r.raise_for_status()
print(r.json())package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
req, err := http.NewRequest("GET", "https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets", nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+os.Getenv("AURAY_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}<?php
$ch = curl_init("https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets");
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("AURAY_API_KEY"),
],
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE), " ", $response, PHP_EOL;require "net/http"
uri = URI("https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets")
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{ENV.fetch("AURAY_API_KEY")}"
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.bodyimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets"))
.header("Authorization", "Bearer " + System.getenv("AURAY_API_KEY"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http.Headers;
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", Environment.GetEnvironmentVariable("AURAY_API_KEY"));
using var request = new HttpRequestMessage(HttpMethod.Get, "https://api.auray.ai/v1/jobs/photo_docs-mtpb1vnh/assets");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");#Responses
#200 OK
OK
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | no | — | |
object | string | no | — | One of "asset_list". |
product | string | no | — | external covers every model somebody else runs, each at its own address. chat is accepted and delivers no webhook event: a chat turn is answered by the request that paid for it. One of "photo", "music", "video", "threed", "chat", "external". |
expires_at | string | no | — | May be null. |
megabytes_charged | integer | no | — | |
assets | object[] | no | — | |
assets[].index | integer | no | — | |
assets[].kind | string | no | — | |
assets[].filename | string | no | — | |
assets[].content_type | string | no | — | |
assets[].bytes | integer | no | — | May be null. |
assets[].url | string | no | — | A URL. |
Headers:
| Header | Description |
|---|---|
RateLimit-Limit | Burst capacity. |
RateLimit-Remaining | |
RateLimit-Reset | Seconds until refill. |
X-RateLimit-Limit | |
X-RateLimit-Remaining | |
X-RateLimit-Reset | Unix seconds. The X- spelling is what client libraries read. |
X-Request-Id |
#401 Unauthorized
#402 Payment Required
#403 Forbidden
#404 Not Found
#409 Conflict
#410 Gone
#413 Payload Too Large
request_too_large — the signed URLs would cost more of the egress bucket than the bucket can ever hold. Ask for a smaller job, or a larger plan.
The error body: error, message, docs (the entry that explains it) and request_id.
#429 Too Many Requests
#500 Internal Server Error
job_read_failed — your job could not be read, which is not the same as having no assets. Retry; nothing was signed and nothing was charged against egress.
The error body: error, message, docs (the entry that explains it) and request_id.
#503 Service Unavailable
#Status codes
| Status | Meaning |
|---|---|
200 | OK |
401 | Unauthorized |
402 | Payment Required |
403 | Forbidden |
404 | Not Found |
409 | Conflict |
410 | Gone |
413 | request_too_large — the signed URLs would cost more of the egress bucket than the bucket can ever hold. |
429 | Too Many Requests |
500 | job_read_failed — your job could not be read, which is not the same as having no assets. |
503 | Service Unavailable |
Every refusal names its code, and every code is explained at Errors.