Upload a file
Uploading is three calls: ask for a signed upload, send the bytes to storage, then add the file to the library. The file becomes an image, video or audio asset in the workspace, ready to place on a board or use as a reference.
1. Get a signed upload
Call createSignedUploadUrl with the file's category, filename and contentType, and your workspaceId. Select uploadForm to get a signed form.
curl https://api.plentylabs.com/graphql \
-H "Authorization: Bearer $PLENTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation CreateSignedUpload($workspaceId: ID!) { createSignedUploadUrl(workspaceId: $workspaceId, category: UGC_IMAGE, filename: \"photo.png\", contentType: \"image/png\") { fileId uploadForm { url fields } } }",
"variables": { "workspaceId": "YOUR_WORKSPACE_ID" }
}' > response.json| Category | Content types |
|---|---|
UGC_IMAGE | image/jpeg, image/jpg, image/png, image/webp, image/avif, image/svg+xml |
AI_IMAGE_REFERENCE | image/jpeg, image/jpg, image/png, image/webp, image/avif |
VIDEO | video/mp4, video/webm, video/quicktime, video/x-msvideo |
AUDIO | audio/mpeg, audio/mp3, audio/wav, audio/x-wav, audio/wave, audio/ogg, audio/aac, audio/webm, audio/mp4, audio/x-m4a, audio/m4a, audio/flac, audio/x-flac |
Any other content type returns BAD_USER_INPUT with the allowed list. UploadCategory in the schema lists every category.
The signed form and URL expire after 15 minutes.
2. Upload the file
POST a multipart form to uploadForm.url. Send every field in uploadForm.fields, then the file last, named file.
UPLOAD_URL=$(jq -r '.data.createSignedUploadUrl.uploadForm.url' response.json)
UPLOAD_FIELDS=$(jq -c '.data.createSignedUploadUrl.uploadForm.fields' response.json)
form=()
while IFS= read -r field; do form+=(-F "$field"); done < <(jq -r 'to_entries[] | "\(.key)=\(.value)"' <<< "$UPLOAD_FIELDS")
curl -f "$UPLOAD_URL" "${form[@]}" -F "file=@photo.png"The form accepts a file from 1 byte to 256 MiB. Any 2xx status means the file is stored.
You can PUT the bytes to signedUrl instead. Send every header in requiredHeaders, exactly as given.
curl -f -X PUT "$SIGNED_URL" \
-H "content-type: image/png" \
-H "x-goog-if-generation-match: 0" \
--data-binary @photo.png3. Add it to the library
Pass the fileId to the mutation for its category. The file becomes an asset in the workspace library.
| Category | Mutation | Returns |
|---|---|---|
UGC_IMAGE, AI_IMAGE_REFERENCE | uploadImage | Image |
VIDEO | uploadVideo | Video |
AUDIO | uploadAudio | Audio |
curl https://api.plentylabs.com/graphql \
-H "Authorization: Bearer $PLENTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation UploadImage($workspaceId: ID!, $fileId: ID!) { uploadImage(workspaceId: $workspaceId, input: { fileId: $fileId, displayName: \"Product photo\" }) { image { id status } } }",
"variables": { "workspaceId": "YOUR_WORKSPACE_ID", "fileId": "FILE_ID" }
}'If the bytes did not arrive, the mutation is refused. Upload again, then retry with the same fileId.
For images and videos, width and height are measured from the file shortly after, when you omit them. Place the asset with PlaceCards.
Files outside the library
For any other category, call confirmFileUpload instead. It keeps the file without adding it to the library. Do not call it for a file you add with a step 3 mutation.
curl https://api.plentylabs.com/graphql \
-H "Authorization: Bearer $PLENTY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation ConfirmFileUpload($fileId: ID!) { confirmFileUpload(fileId: $fileId) }",
"variables": { "fileId": "FILE_ID" }
}'An upload that is neither added nor confirmed is deleted one to two hours after it was requested.
Limits
- A key cannot import a file from a link. Upload the bytes.