Library uploads
Upload a source PNG or DST into a seller's library without a logged-in browser session. A PNG shows up in My designs and in the customizer Files tab. A DST shows up in the DST library and in the customizer DST files tab.
These are source files someone places on a product later. They are not a finished design, and they are not the print URL on an order. Order artwork stays a hosted URL — see Artwork & Print Files.
Authenticate
Send the same API key you use for GraphQL in the x-uid header. Find it under
Settings → Developer → API credentials. See Authentication.
x-uid: YOUR_API_KEY
Content-Type: application/json
The file is saved on the account that owns the key. An enterprise admin can
name a different seller with sellerUid. Any other key cannot.
Find a seller
Enterprise admins can look up sellers in their own enterprise:
GET https://api.riverr.app/dst-library/sellers?q=acme
q is optional. It matches the seller's name, email, or shop name.
{
"sellers": [
{
"uid": "seller_uid",
"name": "Acme Apparel",
"email": "seller@example.com",
"shopNames": ["Acme Store"],
"shops": [{ "id": "shop_id", "name": "Acme Store" }]
}
]
}
Use sellers[].uid as sellerUid on the upload. The seller must be in the
same enterprise as the admin key.
The library belongs to the seller. To file the art under one of their stores
in Design Library, send that store's sellers[].shops[].id as shopId. If you
leave shopId out and the seller has exactly one store, the file is tagged with
that store.
Start an upload
POST https://api.riverr.app/storage/artwork-uploads
{
"name": "crest.png",
"contentType": "image/png",
"size": 240112,
"externalId": "01ABCDEF",
"cTag": "\"c:{ABC},2\"",
"sellerUid": "seller_uid"
}
| Field | Required | What to send |
|---|---|---|
name | yes | File name ending in .png or .dst |
contentType | yes | image/png for a PNG. application/octet-stream for a DST |
size | yes | Size in bytes. Anything over 30MB is refused before a URL is issued |
externalId | yes | A stable id you already have for that file, such as the SharePoint item id. It stays the same when the file is edited |
cTag | yes | A content tag that changes only when the bytes change, such as the SharePoint cTag |
sellerUid | no | Seller uid from the lookup above. Enterprise admin keys only. Omit it to upload into the account that owns the key |
shopId | no | One of that seller's stores, from sellers[].shops[].id. Defaults to the seller's store when they have exactly one |
PNG and DST only.
New file
{
"uploadId": "abc123",
"uploadUrl": "https://storage.googleapis.com/...",
"method": "PUT",
"headers": { "Content-Type": "image/png" },
"expiresInMs": 1800000,
"library": "design",
"sellerUid": "seller_uid"
}
library is design for a PNG and dst for a DST. The URL lasts 30 minutes.
Same file again
If you send the same externalId and the same cTag again for that seller,
there is no uploadUrl. The response is the existing Riverr file, and nothing
new is stored:
{
"id": "file_id",
"url": "https://storage.googleapis.com/...",
"name": "crest.png",
"library": "design",
"sellerUid": "seller_uid"
}
The check is per seller. The same SharePoint file can exist once in each seller's library.
Replacing the bytes
If you send the same externalId and a new cTag, the art changed. You get
an uploadUrl and the existing file id. PUT the new bytes, then call
complete. Riverr keeps that file id and replaces the file behind it.
Upload the bytes
PUT {uploadUrl}
Content-Type: image/png
Send the Content-Type from the start response as the header. The body is the
raw file. The uploaded size must match the size you declared, within 1KB,
and must not be empty or over 30MB.
Finish
POST https://api.riverr.app/storage/artwork-uploads/{uploadId}/complete
No body. The response is the Riverr file:
{
"id": "file_id",
"url": "https://storage.googleapis.com/...",
"name": "crest.png",
"library": "design",
"sellerUid": "seller_uid"
}
url is the permanent public URL. Calling complete again on the same upload
returns the same file.
Store id next to your source file. You do not need it for the duplicate
check — externalId and cTag do that — but it is the id Riverr uses in the
library.
Errors
These calls return JSON { "message", "status" } and use the HTTP status.
They are not GraphQL errors.
| Status | When |
|---|---|
| 400 | Missing or invalid name, type, size, externalId, or cTag. sellerUid is not a seller in this enterprise. shopId is not one of that seller's stores |
| 401 | No account on the request |
| 403 | The API key was rejected, the key is not an enterprise admin and sellerUid names someone else, or the seller's plan does not allow another upload |
| 404 | uploadId does not exist |
| 409 | Complete was called before the PUT finished |
| 413 | The file is over 30MB, or the uploaded bytes are larger than the size you sent |