Documentation: Client Response Gallery
API Documentation
Client Response Gallery exposes a lightweight HTTP API for creating galleries and uploading photos from external tools such as Adobe Lightroom. All requests are authenticated with an API key.
The API is not a REST API in the strict sense: it uses Joomla's standard front-end routing. Every endpoint is a `GET` or `POST` request to your Joomla site's `index.php`.
Configuration
Set the API key under Components > Client Response Gallery > Options > API. The key is generated automatically and is read-only; use the Generate button to create a new one and the Copy button to copy it.
Send it with every request in the `X-API-Key` header. An empty or incorrect key returns `401 Unauthorized`.
Authentication
Every request must include the API key in a custom HTTP header:X-API-Key: your-api-key
A missing or incorrect key returns:HTTP/1.1 401 Unauthorized{"success": false,"message": "Unauthorized"}
Base URL
https://yoursite.com/index.php?option=com_clientresponsegallery&task={endpoint}&format=json
Replace `{endpoint}` with the task name listed for each endpoint below.
Endpoints
List galleries
Returns all published galleries.GET /index.php?option=com_clientresponsegallery&task=api.galleries&format=json
Request headers
| Header | Required | Value |
| `X-API-Key` | Yes | Your API key |
Response: success{"success": true,"galleries": [{ "id": "1", "title": "Wedding 2025", "alias": "wedding-2025" },{ "id": "2", "title": "Family Portraits", "alias": "family-portraits" }]}
The `galleries` array is sorted by title ascending. Unpublished galleries are excluded.
Upload photo
Uploads a photo to an existing gallery. The file is processed (resized, watermarked) according to the component's Batch Upload settings before being saved.POST /index.php?option=com_clientresponsegallery&task=api.upload&format=json
Request headers
Request headers
| Header | Required | Value |
| `X-API-Key` | Yes | Your API key |
| `Content-Type` | Yes | `multipart/form-data` |
Request body (multipart/form-data)
| Field | Type | Required | Description |
| `gallery_id` | integer | Yes | ID of the target gallery |
| `file` | file | Yes | The image to upload |
Accepted file types: `jpg`, `jpeg`, `png`, `webp`. The file content is validated with `getimagesize()`, so renaming a non-image file will not bypass the check.
If a file with the same name already exists in the gallery folder, a timestamp suffix is appended automatically.
Response: success{"success": true}
Response: error{"success": false,"message": "Gallery not found"}
Possible error messages:
| Message | Cause |
| `Missing gallery_id or file` | One of the required fields is absent |
| `Upload error` | PHP reported an upload error |
| `Invalid upload` | File did not pass `is_uploaded_file()` check |
| `Invalid file type` | Extension is not jpg/jpeg/png/webp |
| `Invalid file content` | File content does not match an accepted image format |
| `Gallery not found` | No published gallery exists with the given ID |
| `Failed to save file` | Server could not write the file to disk |
| `Database error` | Photo record could not be inserted |
Create gallery
Creates a new gallery and its folder under `images/clientresponsegallery/`. The gallery is published immediately. The alias is generated from the title and guaranteed to be unique. As of version 1.2.3 the folder name carries a random suffix (for example `spring-session-2025-9f2c1a7b4e08`), so the address of a photo in a protected gallery cannot be guessed from its title.POST /index.php?option=com_clientresponsegallery&task=api.create&format=json
Request headers
| Header | Required | Value |
| `X-API-Key` | Yes | Your API key |
| `Content-Type` | Yes | `multipart/form-data` |
Request body (multipart/form-data)
| Field | Type | Required | Description |
| `title` | string | Yes | Gallery title |
| `description` | string | No | Gallery description (HTML allowed) |
| `password` | string | No | Password required to access the gallery. Stored scrambled, so it cannot be read back afterwards |
| `selection_min` | integer | No | Minimum number of photos the client must select (0 = no minimum) |
| `selection_max` | integer | No | Maximum number of photos the client may select (0 = no maximum) |
| `selection_min_message` | string | No | Warning shown when client selects too few photos. Supports `{MIN_PHOTOS}` and `{MAX_PHOTOS}` placeholders |
| `selection_max_message` | string | No | Warning shown when client selects too many photos. Supports `{MIN_PHOTOS}` and `{MAX_PHOTOS}` placeholders |
Response: success{"success": true,"gallery": {"id": "7","title": "Spring Session 2025","alias": "spring-session-2025"}}
Use the returned `id` immediately in subsequent Upload photo requests.
Response: error{"success": false,"message": "Title is required"}
Error handling
All error responses other than authentication failures return HTTP `200` with `"success": false` and a `message` field. Only `401 Unauthorized` uses a non-200 status code.
All responses include:Content-Type: application/json; charset=utf-8
As of version 1.2.3 no Access-Control-Allow-Origin header is sent. The API authenticates with the X-API-Key header and is meant for server-side callers and desktop clients such as the Lightroom plugin, so a wildcard header only allowed any web page to read the responses. A browser page on another origin can no longer call these endpoints directly.
As of the same version an error message no longer carries the internal technical text. Database error used to arrive with the database exception appended, which exposed table and column names; the message is now short and the detail is written to the Joomla log.
Example: upload a photo with cURL
curl -X POST "https://yoursite.com/index.php?option=com_clientresponsegallery&task=api.upload&format=json" \-H "X-API-Key: your-api-key" \-F "gallery_id=3" \-F "file=@/path/to/photo.jpg"
Example: create a gallery with cURL
curl -X POST "https://yoursite.com/index.php?option=com_clientresponsegallery&task=api.create&format=json" \-H "X-API-Key: your-api-key" \-F "title=Spring Session 2025" \-F "password=secret123" \-F "selection_min=5" \-F "selection_max=20"