HTTP API
Base URL: https://production-transformation-serializer.cloudinary.com
No authentication. Nothing the service returns is customer-scoped, so there is no token to obtain
and no header to set beyond content-type.
Requests are rate limited per IP (600 per 15 minutes by default). If you are encoding on every keystroke in a browser, use the ESM bundle instead — it does the same work locally and does not touch the network at all.
POST /api/v0/encode#
Model → transformation string.
Request
{
"model": [
{ "actionType": "scale", "dimensions": { "width": 200 } },
{ "actionType": "blur", "strength": 500 }
]
}Response 200
{ "transformationString": "c_scale,w_200/e_blur:500" }Every element of model must be an object with a string actionType; other properties are
action-specific and are passed through. An empty model encodes to an empty string.
Qualifiers are emitted in alphabetic order within an action — the canonical form of specification §3.7.
POST /api/v0/decode#
Transformation string → model.
Request
{ "transformationString": "c_scale,w_200/e_blur:500" }Response 200
{
"model": [
{ "actionType": "scale", "dimensions": { "width": 200 } },
{ "actionType": "blur", "strength": 500 }
]
}transformationString is required but may be empty, which decodes to [].
Decoding does not reject unfamiliar syntax: a segment the compiler does not recognise becomes a
custom action holding the raw text, so re-encoding reproduces it. See
specification §4.3.
Errors#
Validation failures return 400 with the offending paths:
{
"errors": [
{ "path": "model.0.actionType", "message": "Invalid input: expected string, received undefined" }
]
}A malformed JSON body returns 400 with { "error": "Invalid JSON payload" }. Exceeding the rate
limit returns 429 with RateLimit-* headers describing the window.
CORS#
/api/v0/encode and /api/v0/decode are restricted to *.cloudinary.com origins (plus localhost for local
development).
If you need /api/v0/encode from another origin, the ESM bundle removes the
question: there is no request to make.