Skip to main content

Downloads

A download is the top-level releaseable unit. It owns versions, files, comments, and per-download team membership. Routes use the internal prefix mc-dm-downloads. The public mount is /api/mc-dm-downloads/.

List downloads

GET /api/mc-dm-downloads/

Scope: mc_dm_download:read.

Filters:

ParamTypeNotes
category_iduintRestrict to a single category.
prefix_iduintRestrict to a single prefix.
download_stateenumvisible, moderated, deleted, or draft. Non-moderator keys are forced to visible.
sinceISO 8601Filters by last_update.

Order whitelist: created_date, last_update, download_count, view_count, title. Default last_update desc.

Permission filter: rows the visitor cannot view are dropped from the page. The pagination.total reflects the pre-filter total, so a visible page may have fewer than per_page rows.

Example

curl -H "XF-Api-Key: $KEY" \
"https://example.com/api/mc-dm-downloads/?category_id=4&order=download_count&direction=desc&per_page=10"

Response

{
"downloads": [
{
"download_id": 42,
"category_id": 4,
"user_id": 17,
"title": "Acme Importer",
"tag_line": "Bulk import via CSV",
"description": "...",
"view_url": "https://example.com/downloads/acme-importer.42/",
"icon_url": "https://example.com/data/mc-downloads/icons/...",
"cover_url": null,
"rating_avg": 4.6,
"rating_count": 12,
"review_count": 9,
"download_count": 318,
"view_count": 2104,
"last_update": 1746200000,
"created_date": 1745000000,
"download_state": "visible",
"prefix_id": 0,
"current_version_id": 88
}
],
"pagination": { "page": 1, "per_page": 10, "total": 87, "last_page": 9 }
}

Get a single download

GET /api/mc-dm-downloads/<download_id>/

Scope: mc_dm_download:read.

Permission: the visitor must pass canView on the download.

curl -H "XF-Api-Key: $KEY" https://example.com/api/mc-dm-downloads/42/

The response is { "download": { ... } } with the same shape as a list element.

Create a download

POST /api/mc-dm-downloads/

Scope: mc_dm_download:write.

Permission: canAddDownload on the target category, or a super-user key.

FieldTypeNotes
category_iduintRequired.
titlestringRequired.
tag_linestringOptional short tagline.
descriptionstringOptional long description. BB code permitted.
prefix_iduintOptional. Must be a prefix assigned to the category.
tagsstring[]Optional. Per-row tag strings.
version_stringstringRequired when the category supports versioning. Defaults to today (Y-m-d) if omitted on a versioning category.

Example

curl -X POST -H "XF-Api-Key: $KEY" \
-d "category_id=4" \
-d "title=Acme Importer" \
-d "tag_line=Bulk import via CSV" \
-d "description=Imports CSV files at scale." \
-d "version_string=1.0.0" \
https://example.com/api/mc-dm-downloads/

Response

{
"download": {
"download_id": 142,
"category_id": 4,
"title": "Acme Importer",
"download_state": "visible",
"current_version_id": 188,
"...": "..."
}
}

If the category requires approval and the visitor does not bypass it, download_state is moderated.

Update a download

PUT /api/mc-dm-downloads/<download_id>/

Scope: mc_dm_download:write.

Permission: canEdit. Changing category_id additionally requires canMove.

FieldType
titlestring
tag_linestring
descriptionstring
prefix_iduint (0 to clear)
category_iduint (move)
tagsstring[]

Fields omitted from the request body are left untouched. An empty string is a deliberate clear. Sending no key at all is a no-op.

curl -X PUT -H "XF-Api-Key: $KEY" \
-d "tag_line=Now with magic" \
https://example.com/api/mc-dm-downloads/142/

Response: { "download": { ... } }.

Delete a download

DELETE /api/mc-dm-downloads/<download_id>/

Scope: mc_dm_download:write always. mc_dm_download:delete_hard is required additionally when hard=1.

Permission: canDelete. Hard delete additionally requires canHardDelete.

ParamEffect
hard1 = hard delete (irreversible). Default 0 = soft delete (recoverable for the retention window).
reasonOptional string written to the audit log.

Soft delete

curl -X DELETE -H "XF-Api-Key: $KEY" \
-d "reason=Spam" \
https://example.com/api/mc-dm-downloads/142/

Hard delete

curl -X DELETE -H "XF-Api-Key: $KEY" \
-d "hard=1" \
-d "reason=DMCA" \
https://example.com/api/mc-dm-downloads/142/

Both return { "success": true }. The audit log records the action type as download.soft_deleted or download.hard_deleted.

Verbose mode (?with=full)

Adds the following keys:

FieldTypeNotes
can_viewboolVisitor permission.
can_editboolVisitor permission.
can_deleteboolVisitor permission.
can_downloadboolVisitor permission.
is_visiblebool
is_password_protectedbool
CategoryobjectEmbedded category result at normal verbosity.
CurrentVersionobjectEmbedded version result at normal verbosity. Present when set.