Creator stores images perfectly well, but it will not resize them, crop to a face, convert to WebP or serve them from a CDN. Cloudinary does all of that from the URL. Upload once from Deluge and every variant you ever need is a query string away.
Good news for once — this API has not moved. The endpoint api.cloudinary.com/v1_1/{cloud_name}/image/upload is unchanged, unsigned uploads with a whitelisted preset still work, and SHA-1 is still the default signature algorithm (SHA-256 is opt-in). Signing code written in 2016 is still correct. The updates here are Deluge-side: getUrl/postUrl replaced with invokeurl, and the file fetched through an OAuth connection rather than a report private link.
creator_oauth_connection to pull the file out of Creator.Cloudinary_URL and Cloudinary_PublicId. Store the public id — it is what lets you delete or transform the asset later.// ============================================
// UPLOAD A CREATOR FILE TO CLOUDINARY (signed)
// ============================================
void Updates.uploadToCloudinary(int recordId)
{
CLOUD_NAME = "YOUR_CLOUD_NAME";
API_KEY = "YOUR_CLOUDINARY_API_KEY";
API_SECRET = "YOUR_CLOUDINARY_API_SECRET";
rec = Photos[ID == recordId];
// 1. Fetch the file out of Creator
imageFile = invokeurl
[
url : "https://creatorapp.zohopublic.com/YOUR_ACCOUNT/YOUR_APP/report/Photos/"
+ recordId + "/Photo/download"
type : GET
connection : "creator_oauth_connection"
];
// 2. Build the signature.
// Sign EVERY param you send except file, cloud_name, resource_type
// and api_key. Sort alphabetically, join with &, then append the
// secret directly with no separator.
timestamp = zoho.currenttime.toString("yyyy-MM-dd HH:mm:ss").toTime().getTime() / 1000;
folder = "creator-uploads";
toSign = "folder=" + folder + "×tamp=" + timestamp;
signature = zoho.encryption.sha1(toSign + API_SECRET);
// 3. Upload
params = Map();
params.put("api_key",API_KEY);
params.put("timestamp",timestamp);
params.put("folder",folder);
params.put("signature",signature);
response = invokeurl
[
url : "https://api.cloudinary.com/v1_1/" + CLOUD_NAME + "/image/upload"
type : POST
parameters : params
files : imageFile
];
secureUrl = response.getJSON("secure_url");
if(secureUrl != null)
{
rec.Cloudinary_URL = secureUrl;
rec.Cloudinary_PublicId = response.getJSON("public_id");
info "Uploaded: " + secureUrl;
}
else
{
// On a bad signature Cloudinary echoes the exact string it expected.
info "Cloudinary error: " + response.toString();
}
}Almost every failed Cloudinary integration is a signature problem, and the rule is precise: take every parameter you are sending except file, cloud_name, resource_type and api_key; write them as name=value; sort them alphabetically by name; join with &; then append your API secret with no separator at all. Hash the result.
Cloudinary will tell you the answer. When a signature is rejected the error echoes back the exact string it expected you to sign — something like String to sign - 'folder=creator-uploads×tamp=1000000000'. Log the full response and compare it against what you built. This turns an afternoon of guessing into two minutes.
/w_300,h_300,c_fill/ into the path gives you a thumbnail with no second upload and no second record. Storing variants is the most common way people overspend here.This script is part of the free Creator Scripts Deluge Library.
All 39 Deluge scripts, the full Zoho Creator course, and every downloadable asset are now free. Get free access →