Documentation

Dynjandi stores your images and serves resized, cropped and re-encoded variants of them from cdn.dynjandi.dev. This page covers the URLs, uploading, API keys, usage and the MCP server.

Reference documents:

URLs

A variant URL is the file id followed by operations. Each operation starts with /-/, and operations apply in order. The file id alone, https://cdn.dynjandi.dev/{id}, is the original.

https://cdn.dynjandi.dev/{id}/-/resize/800x/-/format/webp/-/quality/75/
https://cdn.dynjandi.dev/{id}/-/crop/400x400/center/
https://cdn.dynjandi.dev/{id}/-/scale_crop/1280x400/focal/0.42x0.18/
https://cdn.dynjandi.dev/{id}/-/scale_crop/1280x400/face,attention/

Operations

OperationFormNotes
resizeresize/{w}x{h}, resize/{w}x or resize/x{h}Width, height or both. At least one is required.
cropcrop/{w}x{h}/{position}The position is required.
scale_cropscale_crop/{w}x{h}/{position}The position is optional and defaults to center.
formatformat/{format}jpg is accepted as jpeg.
qualityquality/{n}An integer, or a keyword: lightest is 55, lighter 70, normal and smart 80, better 88 and best 95.

Limits and values

WhatAllowed
Width and height1 to 10,000 pixels
Quality1 to 100
Focal coordinates0 to 1
Formatsjpeg, png, webp, avif
Positionscenter, north, south, east, west, northeast, northwest, southeast, southwest, attention, entropy

Positions

Uploadcare URLs

Uploadcare spellings are accepted and normalised to the canonical form, so both spellings share one cache entry.

UploadcareCanonical
scale_crop/650x300/smartcrop/650x300/face,center
quality/smartquality/80
a trailing /image.jpegignored
empty path segments (//)ignored

Caching

A variant is rendered on its first request and served from the cache after that. Variants are served with Cache-Control: public, max-age=31536000, immutable. A URL the grammar rejects answers 400.

Upload

There are two ways to upload. Both take a multipart/form-data body with a file part and, optionally, focalX and focalY parts. The focal point is set with both fields or neither.

With a public key

POST https://cdn.dynjandi.dev/upload
X-Public-Key: {public key}
Content-Type: multipart/form-data

The public key is the only credential this route checks, so send it from your server and not from a page. A successful upload answers 201 with file, id, url, focalX and focalY. The response is Cache-Control: no-store.

This route reports an error as { "error": "message" }, with a string message.

StatusWhen
400The body is not multipart or cannot be read, there is no file or it is empty, or the focal fields are incomplete or out of range.
401The X-Public-Key header is missing or the key is not valid.
402The workspace does not allow uploads, or the upload would pass its storage cap.
413The file is larger than the project's maximum file size, or larger than its remaining storage quota.

With an API key

POST https://app.dynjandi.dev/api/projects/{id}/files
Authorization: Bearer dyn_...
Content-Type: multipart/form-data

This route reports an error as a JSON body such as { "error": { "code": "NOT_FOUND", "message": "…" } }, where code and message are strings and an optional details object may sit beside them. The statuses are 400, 401, 403, 404 and 429, and, for this route, 402, 413 and 502. A 429 carries Retry-After.

API keys

An API key lets a server call the management API without a browser session.

Sending a key

GET https://app.dynjandi.dev/api/workspace
Authorization: Bearer dyn_...

When a request is refused

StatusWhen
401The key is expired, revoked or malformed, or its owner is disabled, is a superadmin, is no longer a member of the workspace, or is gone. Every one of these answers the same 401.
404The route is not on the list below. A route a key cannot reach answers 404, not 403. Another workspace's project or file also answers 404.
429A key is limited to 120 requests a minute, and a client address to 10 failed attempts a minute. A 429 carries Retry-After: 60.

Routes a key can reach

Only these routes accept a key. Every route in the table also accepts HEAD, except /api/files/{id}/focal-suggestion, which is GET only.

RouteMethods
/api/workspaceGET
/api/workspace/usageGET
/api/projectsGET, POST
/api/projects/{id}GET, PATCH
/api/projects/{id}/filesGET, POST
/api/files/{id}GET, PATCH, DELETE
/api/files/{id}/focal-suggestionGET

Usage

GET /api/workspace/usage reports on the one workspace the key was created for. GET /api/workspace returns the same body. A key names no workspace in the request, because it has exactly one. The body holds:

It does not report delivery bandwidth. Every response is Cache-Control: no-store, and errors use the { "error": { "code": "…", "message": "…" } } body of every management API route.

GET https://app.dynjandi.dev/api/workspace/usage
Authorization: Bearer dyn_...

MCP server

An agent can manage a workspace, build and check variant URLs and read these docs through a remote MCP server. It uses the same API key as the management API.

https://mcp.dynjandi.dev/mcp

Connecting

The field names differ between clients. The URL and the header are what they all need:

{
  "mcpServers": {
    "dynjandi": {
      "type": "http",
      "url": "https://mcp.dynjandi.dev/mcp",
      "headers": {
        "Authorization": "Bearer dyn_..."
      }
    }
  }
}

Keep the configuration file out of version control, as for any other key.

Tools

There are twelve tools. The first nine act on the one workspace the key was created for, and the dashboard checks the key on each of those calls. The last three need no key that is real, only a well-formed bearer, and they never call the dashboard.

ToolWhat it does
get_workspaceReturns the workspace: its plan, status, caps and usage.
list_projectsLists the workspace's projects.
get_projectReturns one project with its file count and bytes used.
create_projectCreates a project. The plan may refuse it, for a cap or an inactive plan.
rename_projectRenames a project. The old name is overwritten.
list_filesLists one page of a project's files, 24 to a page.
get_fileReturns one file's metadata, including its focal point.
set_focal_pointSets a file's focal point, replacing the old one, or clears it with null for both coordinates.
suggest_focal_pointAsks the image service where the file's subject is. Nothing is saved, and each call costs container time.
build_variant_urlBuilds a variant URL from a file id and a list of operations, and checks the operations against the limits above.
parse_variant_urlParses a variant URL, or just its path, into its operations and its canonical URL.
read_docsReturns one section of these docs by heading, or the list of headings.

A tool failure comes back as an error result with an error code and a message, not as an HTTP status. A key the dashboard refuses is one such result.

What is not a tool

Uploading a file and deleting a file are not tools. Both stay on the REST API: see Upload and API keys. A project's public key is never returned by a tool.