Start here
Get a canvas
/v1/studio/projects/{project}/canvases/{canvas}on https://api.auray.ai/v1A canvas and its document, with every node that runs carrying its last run: its status, the jobs it started, what they made (items of the project once filed, the job until then), the failure, the m…
A canvas and its document, with every node that runs carrying its last run: its status, the jobs it started, what they made (items of the project once filed, the job until then), the failure, the member who ran it and whose credits it spent. A run is read off the jobs themselves, never off anything a window sent. Takes a key holding studio:read (or studio:write, which reads too) — Account offers both unticked — or the desktop's own session key. Spends nothing.
#Authentication
Authorization: Bearer auray_sk_… — studio:read, or studio:write, which reads too — Account offers both unticked; the desktop's session key holds both.
#Request
#Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
project | string | yes | |
canvas | string | yes |
#Example request
curl https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/… \
-H "Authorization: Bearer $AURAY_API_KEY"const res = await fetch("https://api.auray.ai/v1/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…", {
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/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…",
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/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…", 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/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…");
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/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…")
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/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…"))
.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/studio/projects/3f0c8a52-6a1d-4e8b-9c2d-7e5f4a3b2c1d/canvases/…");
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 |
|---|---|---|---|---|
object | string | yes | — | One of "canvas". |
id | string | yes | — | |
project_id | string | yes | — | |
name | string | yes | — | 0 to 80 characters. |
rev | integer | yes | — | A save names the rev it was drawn from. 1 to …. |
pages | integer | yes | — | 1 to …. |
nodes | integer | yes | — | 0 to …. |
updated_at | string | yes | — | |
updated_by | null or object | yes | — | Who saved it last, while they are a member; null once they left. |
doc | object | yes | — | A canvas document, version 1: pages (up to 20), each with its viewport, its nodes (up to 1,500 — prompts, generators, uploads and the project's assets, upscalers, editors, notes, stickies, shapes, text, drawn strokes, tables, comment pins, reactions and frames) and the edges wiring an output port into an input port that takes its type. The full shape is published with the Studio's contract; a document that does not read is refused canvas_invalid, naming each problem. A node's run is the server's: anything sent there is ignored. |
doc.v | integer | yes | — | One of 1. |
doc.pages | object[] | yes | — | |
doc.pages[].id | string | yes | — | |
doc.pages[].name | string | yes | — | 0 to 80 characters. |
doc.pages[].viewport | object | yes | — | |
doc.pages[].viewport.x | number | no | — | |
doc.pages[].viewport.y | number | no | — | |
doc.pages[].viewport.zoom | number | no | — | 0.05 to 4. |
doc.pages[].nodes | object[] | yes | — | |
doc.pages[].nodes[].id | string | yes | — | |
doc.pages[].nodes[].kind | string | yes | — | One of "prompt", "number", "upload", "assets", "image_gen", "video_gen", "audio_gen", "llm", "upscale", "edit", "note", "sticky", "shape", "text", "stroke", "table", "comment_pin", "reaction", "frame". |
doc.pages[].nodes[].x | number | yes | — | |
doc.pages[].nodes[].y | number | yes | — | |
doc.pages[].nodes[].w | number | yes | — | |
doc.pages[].nodes[].h | number | yes | — | |
doc.pages[].nodes[].parent | string | no | — | May be null. |
doc.pages[].nodes[].z | integer | no | — | |
doc.pages[].nodes[].locked | boolean | no | — | |
doc.pages[].nodes[].data | object | yes | — | |
doc.pages[].nodes[].run | object | no | — | A node's last run, read off the jobs it started — never written by a request. Null before it ran. May be null. |
doc.pages[].edges | object[] | yes | — | |
doc.pages[].edges[].id | string | yes | — | |
doc.pages[].edges[].from | object | yes | — | |
doc.pages[].edges[].to | object | yes | — | |
bytes | integer | yes | — | The document's size as JSON, which is kept up to 2 MB. 0 to …. |
crdt | string | yes | — | The name the canvas's live edits travel under: canvas: and its id. |
request_id | string | no | — | Mirrored in the X-Request-Id header. |
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
#403 Forbidden
#404 Not Found
#429 Too Many Requests
#500 Internal Server Error
#503 Service Unavailable
#Status codes
| Status | Meaning |
|---|---|
200 | OK. |
401 | Unauthorized |
403 | Forbidden |
404 | Not Found |
429 | Too Many Requests |
500 | Internal Server Error |
503 | Service Unavailable |
Every refusal names its code, and every code is explained at Errors.