curl --request POST \
--url https://api.arcuserp.com/v1/products/{id}/images \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source_url": "https://cdn.example.com/products/widget-front.jpg",
"alt": "<string>",
"position": 0,
"is_primary": true,
"external_source": "<string>",
"external_id": "<string>"
}
'import requests
url = "https://api.arcuserp.com/v1/products/{id}/images"
payload = {
"source_url": "https://cdn.example.com/products/widget-front.jpg",
"alt": "<string>",
"position": 0,
"is_primary": True,
"external_source": "<string>",
"external_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source_url: 'https://cdn.example.com/products/widget-front.jpg',
alt: '<string>',
position: 0,
is_primary: true,
external_source: '<string>',
external_id: '<string>'
})
};
fetch('https://api.arcuserp.com/v1/products/{id}/images', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcuserp.com/v1/products/{id}/images",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'source_url' => 'https://cdn.example.com/products/widget-front.jpg',
'alt' => '<string>',
'position' => 0,
'is_primary' => true,
'external_source' => '<string>',
'external_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.arcuserp.com/v1/products/{id}/images"
payload := strings.NewReader("{\n \"source_url\": \"https://cdn.example.com/products/widget-front.jpg\",\n \"alt\": \"<string>\",\n \"position\": 0,\n \"is_primary\": true,\n \"external_source\": \"<string>\",\n \"external_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.arcuserp.com/v1/products/{id}/images")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source_url\": \"https://cdn.example.com/products/widget-front.jpg\",\n \"alt\": \"<string>\",\n \"position\": 0,\n \"is_primary\": true,\n \"external_source\": \"<string>\",\n \"external_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/products/{id}/images")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"source_url\": \"https://cdn.example.com/products/widget-front.jpg\",\n \"alt\": \"<string>\",\n \"position\": 0,\n \"is_primary\": true,\n \"external_source\": \"<string>\",\n \"external_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"product_id": "11111111-2222-3333-4444-555555555555",
"product_image_id": "aaaa1111-1111-1111-1111-111111111111",
"document_id": "dddd1111-1111-1111-1111-111111111111",
"s3_key": "entities/ent-uuid/products/prod-uuid/abc123.jpg",
"url": "https://arcus-assets-us-east-2.s3.us-east-2.amazonaws.com/entities/ent-uuid/products/prod-uuid/abc123.jpg",
"idempotent": false
}
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}Add a product image
Downloads an image from the supplied URL and stores an Arcus-owned copy, which then appears in both file management and the product’s photo gallery. Idempotent via the Idempotency-Key header; a repeated call with the same source URL or external id reuses the existing image instead of duplicating it.
curl --request POST \
--url https://api.arcuserp.com/v1/products/{id}/images \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source_url": "https://cdn.example.com/products/widget-front.jpg",
"alt": "<string>",
"position": 0,
"is_primary": true,
"external_source": "<string>",
"external_id": "<string>"
}
'import requests
url = "https://api.arcuserp.com/v1/products/{id}/images"
payload = {
"source_url": "https://cdn.example.com/products/widget-front.jpg",
"alt": "<string>",
"position": 0,
"is_primary": True,
"external_source": "<string>",
"external_id": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source_url: 'https://cdn.example.com/products/widget-front.jpg',
alt: '<string>',
position: 0,
is_primary: true,
external_source: '<string>',
external_id: '<string>'
})
};
fetch('https://api.arcuserp.com/v1/products/{id}/images', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcuserp.com/v1/products/{id}/images",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'source_url' => 'https://cdn.example.com/products/widget-front.jpg',
'alt' => '<string>',
'position' => 0,
'is_primary' => true,
'external_source' => '<string>',
'external_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.arcuserp.com/v1/products/{id}/images"
payload := strings.NewReader("{\n \"source_url\": \"https://cdn.example.com/products/widget-front.jpg\",\n \"alt\": \"<string>\",\n \"position\": 0,\n \"is_primary\": true,\n \"external_source\": \"<string>\",\n \"external_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.arcuserp.com/v1/products/{id}/images")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source_url\": \"https://cdn.example.com/products/widget-front.jpg\",\n \"alt\": \"<string>\",\n \"position\": 0,\n \"is_primary\": true,\n \"external_source\": \"<string>\",\n \"external_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/products/{id}/images")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"source_url\": \"https://cdn.example.com/products/widget-front.jpg\",\n \"alt\": \"<string>\",\n \"position\": 0,\n \"is_primary\": true,\n \"external_source\": \"<string>\",\n \"external_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"product_id": "11111111-2222-3333-4444-555555555555",
"product_image_id": "aaaa1111-1111-1111-1111-111111111111",
"document_id": "dddd1111-1111-1111-1111-111111111111",
"s3_key": "entities/ent-uuid/products/prod-uuid/abc123.jpg",
"url": "https://arcus-assets-us-east-2.s3.us-east-2.amazonaws.com/entities/ent-uuid/products/prod-uuid/abc123.jpg",
"idempotent": false
}
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}Authorizations
API key issued per entity via Settings > Developers > API Keys.
Each key carries scopes (e.g. orders:read, products:write).
Bearer token format: Authorization: Bearer ark_live_ent_Test keys use ark_test_ent_. Both are issued per entity
via Settings > Developers > API Keys.
Headers
Client-generated unique key for idempotent POST/PATCH/DELETE operations. Alias for the Idempotency parameter. Max 255 chars. On retry with the same key, the original response is returned without re-executing the operation. Keys expire after 24 hours.
255Path Parameters
UUID of the product to attach the photo to.
Body
Absolute URL of the image to copy. Max 20 MB. JPEG / PNG / WebP.
"https://cdn.example.com/products/widget-front.jpg"
Alt text for the image; defaults to the product title.
Display order of the image within the gallery.
Whether this image is the product's primary photo.
Source-system tag for historical migration (e.g. 'bubble_io', 'versa_cloud'). Used for idempotency.
Source-system image id, persisted for traceability and idempotency.
Response
Image copied into Arcus storage and attached to the product.
Show child attributes
Show child attributes
Was this page helpful?

