API / API reference
Assets
Uploading and managing artwork.
data. Paginated collections add
links and meta.
Errors are never wrapped; see Errors.
/api/v1/projects/{project}/assets
Scope
assets:read
List files stored for this project
Everything in this project's storage folder: a key, a public url and a size for each file.
The key is what you pass to the delete endpoint. The url is what you put in a component's image_url. These files count against the designer's storage quota, so /me is worth reading before a large upload.
curl "https://dustinsdesignerden.com/api/v1/projects/1/assets" \
-H "Authorization: Bearer $DDD_TOKEN"
const res = await fetch('https://dustinsdesignerden.com/api/v1/projects/1/assets', {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();
$response = Http::withToken($token)->get('https://dustinsdesignerden.com/api/v1/projects/1/assets');
$data = $response->json();
res = requests.get(
'https://dustinsdesignerden.com/api/v1/projects/1/assets',
headers={'Authorization': f'Bearer {token}'},
)
data = res.json()
{
"data": []
}
Parameters
-
projectinteger · path required - Project id.
Response: Asset
-
keystring - Storage key. Pass this to the delete endpoint.
-
urlstring - Public URL. Put this in a component's image_url.
-
sizeinteger - Stored size in bytes, after any conversion.
-
namestring - Stored filename.
-
last_modifiedstring - When it was last written. Listings only.
/api/v1/projects/{project}/assets
Scope
assets:write
Upload artwork (multipart)
Field name is file. Images only (jpeg, png, gif, webp, avif, svg), 50 MB max. Optional convert_to_webp / convert_to_avif booleans. Counts against the designer's storage quota.
curl -X POST "https://dustinsdesignerden.com/api/v1/projects/1/assets" \
-H "Authorization: Bearer $DDD_TOKEN" \
-F "file=@artwork.png"
const form = new FormData();
form.append('file', fileInput.files[0]);
const res = await fetch('https://dustinsdesignerden.com/api/v1/projects/1/assets', {
method: 'POST',
headers: { Authorization: `Bearer ${token}` },
body: form,
});
const data = await res.json();
$response = Http::withToken($token)
->attach('file', file_get_contents('artwork.png'), 'artwork.png')
->post('https://dustinsdesignerden.com/api/v1/projects/1/assets');
$data = $response->json();
with open('artwork.png', 'rb') as fh:
res = requests.post(
'https://dustinsdesignerden.com/api/v1/projects/1/assets',
headers={'Authorization': f'Bearer {token}'},
files={'file': fh},
)
data = res.json()
{
"key": "users/8513abae35a92148a8d6ae87/projects/1/dagger.png",
"url": "https://assets.dustinsdesignerden.com/ebf3cf58d1b64d4087087b7a37bc9782:pro-assets/users/8513abae35a92148a8d6ae87/projects/1/dagger.png",
"size": 107,
"name": "dagger.png"
}
Parameters
-
projectinteger · path required - Project id.
Body parameters
-
filefile required - multipart/form-data. jpeg, png, gif, webp, avif or svg. 50 MB max.
-
convert_to_webpboolean - Convert to WebP on the way in.
-
convert_to_avifboolean - Convert to AVIF on the way in.
Response: Asset
-
keystring - Storage key. Pass this to the delete endpoint.
-
urlstring - Public URL. Put this in a component's image_url.
-
sizeinteger - Stored size in bytes, after any conversion.
-
namestring - Stored filename.
-
last_modifiedstring - When it was last written. Listings only.
/api/v1/projects/{project}/assets
Scope
assets:write
Delete a file
Removes one stored file and frees the space against the designer's quota. Address it with the key from the asset listing.
Components pointing at that URL are not changed, so deleting a file that is in use leaves them with a broken image. Repoint or remove those components first. Only keys inside this project's folder can be reached: not the designer's avatar, and not another project's artwork.
curl -X DELETE "https://dustinsdesignerden.com/api/v1/projects/1/assets" \
-H "Authorization: Bearer $DDD_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"key": "users/8513abae35a92148a8d6ae87/projects/1/dagger.png"
}'
const res = await fetch('https://dustinsdesignerden.com/api/v1/projects/1/assets', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"key": "users/8513abae35a92148a8d6ae87/projects/1/dagger.png"
}),
});
const data = await res.json();
$response = Http::withToken($token)->delete('https://dustinsdesignerden.com/api/v1/projects/1/assets', [
'key' => 'users/8513abae35a92148a8d6ae87/projects/1/dagger.png',
]);
$data = $response->json();
res = requests.delete(
'https://dustinsdesignerden.com/api/v1/projects/1/assets',
headers={'Authorization': f'Bearer {token}'},
json={
'key': 'users/8513abae35a92148a8d6ae87/projects/1/dagger.png'
},
)
data = res.json()
{
"deleted": true
}
Parameters
-
projectinteger · path required - Project id.
Body parameters
-
keystring required - The storage key returned by an upload. Must be inside this project's folder.
Response: Deletion result
-
deletedboolean|integer truefor a single delete, or the number removed for a bulk one.-
components_retainedboolean - Only on a group delete. Confirms removing the deck or stack left its components in the project.
/api/v1/projects/{project}/assets/from-url
Scope
assets:write
Mirror artwork you already host
The server fetches the URL and stores a copy in the designer's own storage. Public http(s) only; private, loopback and link-local addresses are refused.
curl -X POST "https://dustinsdesignerden.com/api/v1/projects/1/assets/from-url" \
-H "Authorization: Bearer $DDD_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://cdn.example.com/shield.png"
}'
const res = await fetch('https://dustinsdesignerden.com/api/v1/projects/1/assets/from-url', {
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"url": "https://cdn.example.com/shield.png"
}),
});
const data = await res.json();
$response = Http::withToken($token)->post('https://dustinsdesignerden.com/api/v1/projects/1/assets/from-url', [
'url' => 'https://cdn.example.com/shield.png',
]);
$data = $response->json();
res = requests.post(
'https://dustinsdesignerden.com/api/v1/projects/1/assets/from-url',
headers={'Authorization': f'Bearer {token}'},
json={
'url': 'https://cdn.example.com/shield.png'
},
)
data = res.json()
{
"key": "users/8513abae35a92148a8d6ae87/projects/1/shield.png",
"url": "https://assets.dustinsdesignerden.com/ebf3cf58d1b64d4087087b7a37bc9782:pro-assets/users/8513abae35a92148a8d6ae87/projects/1/shield.png",
"size": 107,
"name": "shield.png"
}
Parameters
-
projectinteger · path required - Project id.
Body parameters
-
urlurl required - Public http(s) URL. Private, loopback and link-local addresses are refused, and redirects are followed only while they stay public.
-
convert_to_webpboolean - Convert to WebP.
-
convert_to_avifboolean - Convert to AVIF.
Response: Asset
-
keystring - Storage key. Pass this to the delete endpoint.
-
urlstring - Public URL. Put this in a component's image_url.
-
sizeinteger - Stored size in bytes, after any conversion.
-
namestring - Stored filename.
-
last_modifiedstring - When it was last written. Listings only.