API
Resources 🔗
Responses and Error Handling 🔗
If there is an error, the response will be JSON similar to the following with a non-200 status code:
{
"success": false,
"error": "The error message"
}
Successful GET requests will return the resource's information directly as a JSON response.
Other successful results will return a dictionary with success
equaling true, and
often other keys with information. For example:
{
"success": true,
"release": {
/* same as returned by a GET */
}
}
Paginated Results 🔗
Some API endpoints returns results in pages. The page number is specified using the page
query argument, and
the number of items is specified using num
The response will be a dictionary with the following keys:
page
: page number, integer from 1 to maxper_page
: number of items per page, same asn
page_count
: number of pagestotal
: total number of resultsurls
: dictionary containingnext
: url to next pageprevious
: url to previous page
items
: array of items
Authentication 🔗
Not all endpoints require authentication, but it is done using Bearer tokens:
curl https://content.luanti.org/api/whoami/ \
-H "Authorization: Bearer YOURTOKEN"
Tokens can be attained by visiting Settings > API Tokens.
- GET
/api/whoami/
: JSON dictionary with the following keys:is_authenticated
: True on successful API authenticationusername
: Username of the user authenticated as, null otherwise.- 4xx status codes will be thrown on unsupported authentication type, invalid access token, or other errors.
- DELETE
/api/delete-token/
: Deletes the currently used token.
# Logout
curl -X DELETE https://content.luanti.org/api/delete-token/ \
-H "Authorization: Bearer YOURTOKEN"
Packages 🔗
- GET
/api/packages/
(List)- See Package Queries
- GET
/api/packages/<username>/<name>/
(Read)- Redirects a JSON object with the keys documented by the PUT endpoint, below.
- Plus:
forum_url
: String or null.
- PUT
/api/packages/<author>/<name>/
(Update)- Requires authentication.
- JSON object with any of these keys (all are optional, null to delete Nullables):
type
: One ofGAME
,MOD
,TXP
.title
: Human-readable title.name
: Technical name (needs permission if already approved).short_description
dev_state
: One ofWIP
,BETA
,ACTIVELY_DEVELOPED
,MAINTENANCE_ONLY
,AS_IS
,DEPRECATED
,LOOKING_FOR_MAINTAINER
.tags
: List of tag names.content_warnings
: List of content warning names.license
: A license name.media_license
: A license name.long_description
: Long markdown description.repo
: Source repository (eg: Git)website
: Website URL.issue_tracker
: Issue tracker URL.forums
: forum topic ID.video_url
: URL to a video.donate_url
: URL to a donation page.translation_url
: URL to send users interested in translating your package.game_support
: Array of game support information objects. Not currently documented,
- Returns a JSON object with:
success
package
: updated packagewas_modified
: bool, whether anything changed
- GET
/api/packages/<username>/<name>/for-client/
- Similar to the read endpoint, but optimised for the Luanti client
long_description
is given as a hypertext object, see/hypertext/
below.info_hypertext
is the info sidebar as a hypertext object.- Query arguments
formspec_version
: Required. See /hypertext/ below.include_images
: Optional, defaults to true. If true, images use<img>
. If false, they're linked.protocol_version
: Optional, used to get the correct release.engine_version
: Optional, used to get the correct release. Ex:5.3.0
.
- GET
/api/packages/<username>/<name>/for-client/reviews/
- Returns hypertext representing the package's reviews
- Query arguments
formspec_version
: Required. See /hypertext/ below.
- Returns JSON dictionary with following keys:
head
: markup for suggested styling and custom tags, prepend to the body before displaying.body
: markup for long description.links
: dictionary of anchor name to link URL.images
: dictionary of img name to image URL.image_tooltips
: dictionary of img name to tooltip text.
- The hypertext body contains some placeholders that should be replaced client-side:
<thumbsup>
with a thumbs up icon.<neutral>
with a thumbs up icon.<thumbsdown>
with a thumbs up icon.
- GET
/api/packages/<author>/<name>/hypertext/
- Converts the long description to Luanti Markup Language
to be used in a
hypertext
formspec element. - Query arguments:
formspec_version
: Required, maximum supported formspec version.include_images
: Optional, defaults to true. If true, images use<img>
. If false, they're linked.
- Returns JSON dictionary with following keys:
head
: markup for suggested styling and custom tags, prepend to the body before displaying.body
: markup for long description.links
: dictionary of anchor name to link URL.images
: dictionary of img name to image URL.image_tooltips
: dictionary of img name to tooltip text.
- Converts the long description to Luanti Markup Language
to be used in a
- GET
/api/packages/<username>/<name>/dependencies/
- Returns dependencies, with suggested candidates
- If query argument
only_hard
is present, only hard deps will be returned.
- GET
/api/dependencies/
- Returns
provides
and raw dependencies for all packages. - Supports Package Queries
- Paginated result, max 300 results per page
- Each item in
items
will be a dictionary with the following keys:type
: One ofGAME
,MOD
,TXP
.author
: Username of the package author.name
: Package name.provides
: List of technical mod names inside the package.depends
: List of hard dependencies.- Each dep will either be a modname dependency (
name
), or a package dependency (author/name
).
- Each dep will either be a modname dependency (
optional_depends
: list of optional dependencies- Same as above.
- Returns
- GET
/api/packages/<username>/<name>/stats/
- Returns daily stats for package, or null if there is no data.
- Daily date is done based on the UTC timezone.
- EXPERIMENTAL. This API may change without warning.
- Query args:
start
: start date, inclusive. Optional. Default: 2022-10-01. UTC.end
: end date, inclusive. Optional. Default: today. UTC.
- An object with the following keys:
start
: start date, inclusive. Ex: 2022-10-22. Mend
: end date, inclusive. Ex: 2022-11-05.platform_minetest
: list of integers per day.platform_other
: list of integers per day.reason_new
: list of integers per day.reason_dependency
: list of integers per day.reason_update
: list of integers per day.
- GET
/api/package_stats/
- Returns last 30 days of daily stats for all packages.
- An object with the following keys:
start
: start date, inclusive. Ex: 2022-10-22.end
: end date, inclusive. Ex: 2022-11-05.package_downloads
: map from package key to list of download integers.
You can download a package by building one of the two URLs:
https://content.luanti.org/packages/${author}/${name}/download/`
https://content.luanti.org/packages/${author}/${name}/releases/${release}/download/`
Examples:
# Edit package
curl -X PUT https://content.luanti.org/api/packages/username/name/ \
-H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \
-d '{ "title": "Foo bar", "tags": ["pvp", "survival"], "license": "MIT" }'
# Remove website URL
curl -X PUT https://content.luanti.org/api/packages/username/name/ \
-H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \
-d '{ "website": null }'
Package Queries 🔗
Example:
/api/packages/?type=mod&type=game&q=mobs+fun&hide=nonfree&hide=gore
Filter query parameters:
type
: Filter by package type (mod
,game
,txp
). Multiple types are OR-ed together.q
: Query string.author
: Filter by author.tag
: Filter by tags. Multiple tags are AND-ed together.flag
: Filter to show packages with Content Flags.hide
: Hide content based on tags or Content Flags.license
: Filter by license name. Multiple licenses are OR-ed together, ie:&license=MIT&license=LGPL-2.1-only
game
: Filter by Game Support, ex:Warr1024/nodecore
. (experimental, doesn't show items that support every game currently).lang
: Filter by translation support, eg:en
/de
/ja
/zh_TW
.protocol_version
: Only show packages supported by this Luanti protocol version.engine_version
: Only show packages supported by this Luanti engine version, eg:5.3.0
.
Sorting query parameters:
sort
: Sort by (name
,title
,score
,reviews
,downloads
,created_at
,approved_at
,last_release
).order
: Sort ascending (asc
) or descending (desc
).random
: When present, enable random ordering and ignoresort
.
Format query parameters:
limit
: Return at mostlimit
packages.fmt
: How the response is formatted.keys
: author/name only.short
: stuff needed for the Luanti client.vcs
:short
but withrepo
.
Releases 🔗
- GET
/api/releases/
(List)- Limited to 30 most recent releases.
- Optional arguments:
author
: Filter by authormaintainer
: Filter by maintainer
- Returns array of release dictionaries with keys:
id
: release IDname
: short release nametitle
: human-readable titlerelease_notes
: string or null, what's new in this release. Markdown.release_date
: Date releasedurl
: download URLcommit
: commit hash or nulldownloads
: number of downloadsmin_minetest_version
: dict or null, minimum supported Luanti version (inclusive).max_minetest_version
: dict or null, minimum supported Luanti version (inclusive).size
: size of zip file, in bytes.package
author
: author usernamename
: technical nametype
:mod
,game
, ortxp
- GET
/api/updates/
(Look-up table)- Returns a look-up table from package key (
author/name
) to latest release id - Query arguments
protocol_version
: Only show packages supported by this Luanti protocol version.engine_version
: Only show packages supported by this Luanti engine version, eg:5.3.0
.
- Returns a look-up table from package key (
- GET
/api/packages/<username>/<name>/releases/
(List)- Returns array of release dictionaries, see above, but without package info.
- GET
/api/packages/<username>/<name>/releases/<id>/
(Read) - POST
/api/packages/<username>/<name>/releases/new/
(Create)- Requires authentication.
- Body can be JSON or multipart form data. Zip uploads must be multipart form data.
title
: human-readable name of the release.release_notes
: string or null, what's new in this release.- For Git release creation:
method
: must begit
.ref
: (Optional) git reference, eg:master
.
- For zip upload release creation:
file
: multipart file to upload, like<input type="file" name="file">
.commit
: (Optional) Source Git commit hash, for informational purposes.
- You can set min and max Luanti Versions using the content's .conf file.
- DELETE
/api/packages/<username>/<name>/releases/<id>/
(Delete)- Requires authentication.
- Deletes release.
Examples:
# Create release from Git
curl -X POST https://content.luanti.org/api/packages/username/name/releases/new/ \
-H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \
-d '{
"method": "git",
"name": "1.2.3",
"title": "My Release",
"ref": "master",
"release_notes": "some\nrelease\nnotes\n"
}'
# Create release from zip upload
curl -X POST https://content.luanti.org/api/packages/username/name/releases/new/ \
-H "Authorization: Bearer YOURTOKEN" \
-F title="My Release" -F file=@path/to/file.zip
# Create release from zip upload with commit hash
curl -X POST https://content.luanti.org/api/packages/username/name/releases/new/ \
-H "Authorization: Bearer YOURTOKEN" \
-F title="My Release" -F commit="8ef74deec170a8ce789f6055a59d43876d16a7ea" -F file=@path/to/file.zip
# Delete release
curl -X DELETE https://content.luanti.org/api/packages/username/name/releases/3/ \
-H "Authorization: Bearer YOURTOKEN"
Screenshots 🔗
- GET
/api/packages/<username>/<name>/screenshots/
(List)- Returns array of screenshot dictionaries with keys:
id
: screenshot IDapproved
: true if approved and visible.title
: human-readable name for the screenshot, shown as a caption and alt text.url
: absolute URL to screenshot.created_at
: ISO time.order
: Number used in ordering.is_cover_image
: true for cover image.
- Returns array of screenshot dictionaries with keys:
- GET
/api/packages/<username>/<name>/screenshots/<id>/
(Read)- Returns screenshot dictionary like above.
- POST
/api/packages/<username>/<name>/screenshots/new/
(Create)- Requires authentication.
- Body is multipart form data.
title
: human-readable name for the screenshot, shown as a caption and alt text.file
: multipart file to upload, like<input type=file>
.is_cover_image
: set cover image to this.
- DELETE
/api/packages/<username>/<name>/screenshots/<id>/
(Delete)- Requires authentication.
- Deletes screenshot.
- POST
/api/packages/<username>/<name>/screenshots/order/
- Requires authentication.
- Body is a JSON array containing the screenshot IDs in their order.
- POST
/api/packages/<username>/<name>/screenshots/cover-image/
- Requires authentication.
- Body is a JSON dictionary with "cover_image" containing the screenshot ID.
Currently, to get a different size of thumbnail you can replace the number in /thumbnails/1/
with any number from 1-3.
The resolutions returned may change in the future, and we may move to a more capable thumbnail generation.
Examples:
# Create screenshot
curl -X POST https://content.luanti.org/api/packages/username/name/screenshots/new/ \
-H "Authorization: Bearer YOURTOKEN" \
-F title="My Release" -F file=@path/to/screnshot.png
# Create screenshot and set it as the cover image
curl -X POST https://content.luanti.org/api/packages/username/name/screenshots/new/ \
-H "Authorization: Bearer YOURTOKEN" \
-F title="My Release" -F file=@path/to/screnshot.png -F is_cover_image="true"
# Delete screenshot
curl -X DELETE https://content.luanti.org/api/packages/username/name/screenshots/3/ \
-H "Authorization: Bearer YOURTOKEN"
# Reorder screenshots
curl -X POST https://content.luanti.org/api/packages/username/name/screenshots/order/ \
-H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \
-d "[13, 2, 5, 7]"
# Set cover image
curl -X POST https://content.luanti.org/api/packages/username/name/screenshots/cover-image/ \
-H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \
-d "{ 'cover_image': 123 }"
Reviews 🔗
- GET
/api/packages/<username>/<name>/reviews/
(List)- Returns array of review dictionaries with keys:
user
: dictionary withdisplay_name
andusername
.title
: review titlecomment
: the textrating
: 1 for negative, 3 for neutral, 5 for positiveis_positive
: booleancreated_at
: iso timestampvotes
: dictionary withhelpful
andunhelpful
,
- Returns array of review dictionaries with keys:
- GET
/api/reviews/
(List)- Returns a paginated response. This is a dictionary with
page
,url
, anditems
.- Paginated result
items
: array of review dictionaries, like above- Each review also has a
package
dictionary withtype
,author
andname
- Each review also has a
- Ordered by created at, newest to oldest.
- Query arguments:
page
: page number, integer from 1 to maxn
: number of results per page, max 200author
: filter by review author usernamefor_user
: filter by package authorrating
: 1 for negative, 3 for neutral, 5 for positiveis_positive
: true or false. Default: nullq
: filter by title (case-insensitive, no fulltext search)
- Returns a paginated response. This is a dictionary with
Example:
[
{
"comment": "This is a really good mod!",
"created_at": "2021-11-24T16:18:33.764084",
"is_positive": true,
"title": "Really good",
"user": {
"display_name": "rubenwardy",
"username": "rubenwardy"
},
"votes": {
"helpful": 0,
"unhelpful": 0
}
}
]
Users 🔗
- GET
/api/users/<username>/
username
display_name
: human-readable name to be displayed in GUIs.rank
: ContentDB rank.profile_pic_url
: URL to profile picture, or null.website_url
: URL to website, or null.donate_url
: URL to donate page, or null.connections
: objectgithub
: GitHub username, or null.forums
: forums username, or null.
links
: objectapi_packages
: URL to API to list this user's packages.profile
: URL to the HTML profile page.
- GET
/api/users/<username>/stats/
- Returns daily stats for the user's packages, or null if there is no data.
- Daily date is done based on the UTC timezone.
- EXPERIMENTAL. This API may change without warning.
- Query args:
start
: start date, inclusive. Optional. Default: 2022-10-01. UTC.end
: end date, inclusive. Optional. Default: today. UTC.
- A table with the following keys:
from
: start date, inclusive. Ex: 2022-10-22.end
: end date, inclusive. Ex: 2022-11-05.package_downloads
: map of package title to list of integers per day.platform_minetest
: list of integers per day.platform_other
: list of integers per day.reason_new
: list of integers per day.reason_dependency
: list of integers per day.reason_update
: list of integers per day.
Topics 🔗
- GET
/api/topics/
(View)- See Topic Queries
Topic Queries 🔗
Example:
/api/topics/?q=mobs&type=mod&type=game
Supported query parameters:
q
: Query string.type
: Package types (mod
,game
,txp
).sort
: Sort by (name
,views
,created_at
).show_added
: Show topics that have an existing package.limit
: Return at mostlimit
topics.
Collections 🔗
- GET
/api/collections/
- Query args:
author
: collection author username.package
: collections that contain the package.
- Returns JSON array of collection entries:
author
: author username.name
: collection name.title
short_description
created_at
: creation time in iso format.private
: whether collection is private, boolean.package_count
: number of packages, integer.
- Query args:
- GET
/api/collections/<username>/<name>/
- Returns JSON object for collection:
author
: author username.name
: collection name.title
short_description
long_description
created_at
: creation time in iso format.private
: whether collection is private, boolean.items
: array of item objects:package
: short info about the package.description
: custom short description.created_at
: when the package was added to the collection.order
: integer.
- Returns JSON object for collection:
Types 🔗
Tags 🔗
- GET
/api/tags/
(View)- List of objects with:
name
: technical name.title
: human-readable title.description
: tag description or null.views
: number of views of this tag.
- List of objects with:
Content Warnings 🔗
- GET
/api/content_warnings/
(View)- List of objects with
name
: technical nametitle
: human-readable titledescription
: tag description or null
- List of objects with
Licenses 🔗
- GET
/api/licenses/
(View)- List of objects with:
name
is_foss
: whether the license is foss
- List of objects with:
Luanti Versions 🔗
- GET
/api/minetest_versions/
(View)- List of objects with:
name
: Version name.is_dev
: boolean, is dev version.protocol_version
: protocol version number.
- List of objects with:
Languages 🔗
- GET
/api/languages/
(View)- List of objects with:
id
: language code.title
: native language name.has_contentdb_translation
: whether ContentDB has been translated into this language.
- List of objects with:
Misc 🔗
- GET
/api/scores/
(View)- See Top Packages Algorithm.
- Supports Package Queries.
- Returns list of:
author
: package author name.name
: package technical name.downloads
: number of downloads.score
: total package score.score_reviews
: score from reviews.score_downloads
: score from downloads.reviews
: a dictionary ofpositive
: int, number of positive reviews.neutral
: int, number of neutral reviews.negative
: int, number of negative reviews.
- GET
/api/homepage/
(View) - get contents of homepage.count
: number of packagesdownloads
: get number of downloadsnew
: new packagesupdated
: recently updated packagespop_mod
: popular modspop_txp
: popular texturespop_game
: popular gameshigh_reviewed
: highest reviewed
- GET
/api/cdb_schema/
(View)- Get JSON Schema of
.cdb.json
, including licenses, tags and content warnings. - See JSON Schema Reference.
- Get JSON Schema of
- POST
/api/hypertext/
- Converts HTML or Markdown to Luanti Markup Language
to be used in a
hypertext
formspec element. - Post data: HTML or Markdown as plain text.
- Content-Type:
text/html
ortext/markdown
. - Query arguments:
formspec_version
: Required, maximum supported formspec version. Ie: 6include_images
: Optional, defaults to true. If true, images use<img>
. If false, they're linked.
- Returns JSON dictionary with following key:
head
: markup for suggested styling and custom tags, prepend to the body before displaying.body
: markup for long description.links
: dictionary of anchor name to link URL.images
: dictionary of img name to image URLimage_tooltips
: dictionary of img name to tooltip text.
- Converts HTML or Markdown to Luanti Markup Language
to be used in a