REST API

A REST API for publishing and deleting app releases has been built into the store from day one to help release automation.

API Stability Contract

The API level will change if the following occurs:

  • a required HTTP request header is added
  • a required request parameter is added
  • a JSON field of a response object is removed
  • a JSON field of a response object is changed to appear optionally
  • a JSON field of a response object is changed to a different datatype
  • an explicitly documented HTTP response header is removed
  • an explicitly documented HTTP response header is changed to a different datatype
  • the meaning of an API call changes

The API level will not change if:

  • a new HTTP response header is added
  • an optional new HTTP request header is added
  • a new response parameter is added
  • the order of the JSON attributes is changed
  • if app validation after uploading an app release is changed in any way

You have to design your app with these things in mind:

  • Don’t depend on the order of object attributes. In JSON it does not matter where the object attribute is since you access the value by name, not by index
  • Don’t limit your app to the currently available attributes. New ones might be added. If you don’t handle them, ignore them
  • Use a library to compare versions, ideally one that uses semantic versioning

Authentication

Several routes require authentication. The following authentication methods are supported:

  • Basic: Http header where CREDENTIALS is base64encode('user:password'):

    Authorization: Basic CREDENTIALS
    
  • Token: Http header where TOKEN is a token which can be looked up in your account settings or acquired through the API:

    Authorization: Token TOKEN
    

Note

If you created your account using GitHub you will always need to use token authentication since we do not have access to your password. The token can be looked up in your account settings

Specification

The following API routes are present:

Get API Token

This route will return the API token for the authenticated user. If no token exists, one will be generated.

  • Url: POST /api/v1/token

  • Authentication: Basic, Session

  • Example CURL request:

    curl -X POST https://apps.nextcloud.com/api/v1/token -u "user:password"
    
  • Returns: application/json

{"token":"4b92477ff8d5fe889be75db4c7d9a09116276920"}

Regenerate API Token

This route will generate and return a new API token for the authenticated user regardless of whether a token already exists.

  • Url: POST /api/v1/token/new

  • Authentication: Basic, Token

  • Example CURL request:

    curl -X POST https://apps.nextcloud.com/api/v1/token/new -u "user:password"
    
  • Returns: application/json

{"token":"ca3fb97920705d2c2ecdb0900f8ed5cf5744704d"}

Get All Categories

This route will return all categories and their translations.

  • Url: GET /api/v1/categories.json

  • Authentication: None

  • Caching: ETag

  • Example CURL request:

    curl https://apps.nextcloud.com/api/v1/categories.json -H 'If-None-Match: "4-2016-06-11 10:37:24+00:00"'
    
  • Returns: application/json

[
    {
        "id": "games",
        "translations": {
            "en": {
                "name": "Games",
                "description": ""
            },
            "de": {
                "name": "Spiele",
                "description": ""
            },
            "fr": {
                "name": "Jeux",
                "description": ""
            }
        }
    },
    {
        "id": "multimedia",
        "translations": {
            "en": {
                "name": "Multimedia",
                "description": ""
            },
            "de": {
                "name": "Multimedia",
                "description": ""
            },
            "fr": {
                "name": "Multimedia",
                "description": ""
            }
        }
    },
    {
        "id": "pim",
        "translations": {
            "en": {
                "name": "PIM",
                "description": ""
            },
            "de": {
                "name": "PIM",
                "description": ""
            },
            "fr": {
                "name": "PIM",
                "description": ""
            }
        }
    },
    {
        "id": "tools",
        "translations": {
            "en": {
                "name": "Tools",
                "description": ""
            },
            "de": {
                "name": "Werkzeuge",
                "description": ""
            },
            "fr": {
                "name": "Outil",
                "description": ""
            }
        }
    }
]
translations
Translated fields are stored inside a translations object. They can have any size, depending on if there is a translation. If a required language is not found, you should fall back to English.

Get All Apps and Releases

This route will return all releases to display inside Nextcloud’s apps admin area.

  • Url: GET /api/v1/platform/{platform-version}/apps.json

  • Url parameters:

    • platform-version: semantic version, digits only: Returns all the apps and their releases that work on this version. If an app has no working releases, the app will be excluded
  • Authentication: None

  • Caching: ETag

  • Example CURL request:

    curl https://apps.nextcloud.com/api/v1/platform/9.0.0/apps.json -H 'If-None-Match: "1-1-2016-06-17 23:08:58.042321+00:00"'
    
  • Returns: application/json

[
    {
        "id": "news",
        "categories": [
            "multimedia"
        ],
        "authors": [
            {
                "name": "Bernhard Posselt",
                "mail": "",
                "homepage": ""
            },
            {
                "name": "Alessandro Cosentino",
                "mail": "",
                "homepage": ""
            },
            {
                "name": "Jan-Christoph Borchardt",
                "mail": "",
                "homepage": ""
            }
        ],
        "userDocs": "https://github.com/owncloud/news/wiki#user-documentation",
        "adminDocs": "https://github.com/owncloud/news#readme",
        "developerDocs": "https://github.com/owncloud/news/wiki#developer-documentation",
        "issueTracker": "https://github.com/owncloud/news/issues",
        "website": "https://github.com/owncloud/news",
        "discussion": "https://help.nextcloud.com/c/apps/news",
        "created": "2016-06-25T16:08:56.794719Z",
        "lastModified": "2016-06-25T16:49:25.326855Z",
        "ratingOverall": 0.5,
        "ratingNumOverall": 20,
        "ratingRecent": 1.0,
        "ratingNumRecent": 10,
        "releases": [
            {
                "version": "9.0.4-alpha.1",
                "phpExtensions": [
                    {
                        "id": "libxml",
                        "versionSpec": ">=2.7.8",
                        "rawVersionSpec": ">=2.7.8"
                    },
                    {
                        "id": "curl",
                        "versionSpec": "*",
                        "rawVersionSpec": "*"
                    },
                    {
                        "id": "SimpleXML",
                        "versionSpec": "*",
                        "rawVersionSpec": "*"
                    },
                    {
                        "id": "iconv",
                        "versionSpec": "*",
                        "rawVersionSpec": "*"
                    }
                ],
                "databases": [
                    {
                        "id": "pgsql",
                        "versionSpec": ">=9.4.0",
                        "rawVersionSpec": ">=9.4"
                    },
                    {
                        "id": "sqlite",
                        "versionSpec": "*",
                        "rawVersionSpec": "*"
                    },
                    {
                        "id": "mysql",
                        "versionSpec": ">=5.5.0",
                        "rawVersionSpec": ">=5.5"
                    }
                ],
                "shellCommands": [
                    "grep"
                ],
                "phpVersionSpec": ">=5.6.0",
                "platformVersionSpec": ">=9.0.0 <9.2.0",
                "rawPhpVersionSpec": ">=5.6",
                "rawPlatformVersionSpec": ">=10 <=10",
                "minIntSize": 64,
                "isNightly": false,
                "download": "https://github.com/owncloud/news/releases/download/8.8.0/news.tar.gz",
                "created": "2016-06-25T16:08:56.796646Z",
                "licenses": [
                    "agpl"
                ],
                "lastModified": "2016-06-25T16:49:25.319425Z",
                "signature": "909377e1a695bbaa415c10ae087ae1cc48e88066d20a5a7a8beed149e9fad3d5",
                "translations": {
                    "en": {
                        "changelog": "* **Bugfix**: Pad API last modified timestamp to milliseconds in updated items API to return only new items. API users however need to re-sync their complete contents, #24\n* **Bugfix**: Do not pad milliseconds for non millisecond timestamps in API"
                    }
                }
            }
        ],
        "screenshots": [
            {
                "url": "https://example.com/news.jpg",
                "smallThumbnail": ""
            }
        ],
        "translations": {
            "en": {
                "name": "News",
                "summary": "An RSS/Atom feed reader",
                "description": "# This is markdown\nnext line"
            }
        },
        "isFeatured": false,
        "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEojCCA4qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUx\r\nGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzEXMBUGA1UECgwOTmV4dGNsb3Vk\r\nIEdtYkgxNjA0BgNVBAMMLU5leHRjbG91ZCBDb2RlIFNpZ25pbmcgSW50ZXJtZWRp\r\nYXRlIEF1dGhvcml0eTAeFw0xNjA2MTIyMTA1MDZaFw00MTA2MDYyMTA1MDZaMGYx\r\nCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxEjAQBgNV\r\nBAcMCVN0dXR0Z2FydDEXMBUGA1UECgwOTmV4dGNsb3VkIEdtYkgxDTALBgNVBAMM\r\nBGNvcmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUxcrn2DC892IX\r\n8+dJjZVh9YeHF65n2ha886oeAizOuHBdWBfzqt+GoUYTOjqZF93HZMcwy0P+xyCf\r\nQqak5Ke9dybN06RXUuGP45k9UYBp03qzlUzCDalrkj+Jd30LqcSC1sjRTsfuhc+u\r\nvH1IBuBnf7SMUJUcoEffbmmpAPlEcLHxlUGlGnz0q1e8UFzjbEFj3JucMO4ys35F\r\nqZS4dhvCngQhRW3DaMlQLXEUL9k3kFV+BzlkPzVZEtSmk4HJujFCnZj1vMcjQBg\/\r\nBqq1HCmUB6tulnGcxUzt\/Z\/oSIgnuGyENeke077W3EyryINL7EIyD4Xp7sxLizTM\r\nFCFCjjH1AgMBAAGjggFDMIIBPzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIG\r\nQDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRp\r\nZmljYXRlMB0GA1UdDgQWBBQwc1H9AL8pRlW2e5SLCfPPqtqc0DCBpQYDVR0jBIGd\r\nMIGagBRt6m6qqTcsPIktFz79Ru7DnnjtdKF+pHwwejELMAkGA1UEBhMCREUxGzAZ\r\nBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzESMBAGA1UEBwwJU3R1dHRnYXJ0MRcw\r\nFQYDVQQKDA5OZXh0Y2xvdWQgR21iSDEhMB8GA1UEAwwYTmV4dGNsb3VkIFJvb3Qg\r\nQXV0aG9yaXR5ggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH\r\nAwEwDQYJKoZIhvcNAQELBQADggEBADZ6+HV\/+0NEH3nahTBFxO6nKyR\/VWigACH0\r\nnaV0ecTcoQwDjKDNNFr+4S1WlHdwITlnNabC7v9rZ\/6QvbkrOTuO9fOR6azp1EwW\r\n2pixWqj0Sb9\/dSIVRpSq+jpBE6JAiX44dSR7zoBxRB8DgVO2Afy0s80xEpr5JAzb\r\nNYuPS7M5UHdAv2dr16fDcDIvn+vk92KpNh1NTeZFjBbRVQ9DXrgkRGW34TK8uSLI\r\nYG6jnfJ6eJgTaO431ywWPXNg1mUMaT\/+QBOgB299QVCKQU+lcZWptQt+RdsJUm46\r\nNY\/nARy4Oi4uOe88SuWITj9KhrFmEvrUlgM8FvoXA1ldrR7KiEg=\r\n-----END CERTIFICATE-----",
        "signatureDigest": "sha512"
    }
]
translations
Translated fields are stored inside a translations object. They can have any size, depending on if there is a translation. If a required language is not found, you should fall back to English.
isNightly
True if the release is a nightly version. New nightly releases are not required to have a higher version than the previous one to be considered greater. Instead look at the lastModified attribute to detect updates if both nightly versions are equal. Example: 1.0.0 is equal to 1.0.0, however if the second one has a nightly flag, then the second one is greater. If both versions have nightly flags and are equal, the lastModified is used to determine the precedence.
screenshots
Guaranteed to be HTTPS
smallThumbnail
Small thumbnail which can be used as preview image. Guaranteed to be HTTPS. Not required, so if not present or an empty string, use the screenshot url instead.
download
Download archive location, guaranteed to be HTTPS
versionSpec

Required versions (minimum and maximum versions) are transformed to semantic version specs. If a field is a *, this means that there is no version requirement. The following permutations can occur:

  • All versions: *
  • Maximum version only: <8.1.2
  • Minimum version only: >=9.3.2
  • Maximum and minimum version: >=9.3.2 <8.1.2
rawVersionSpec

Non semantic versions as they occur in the info.xml. The following permutations can occur:

  • All versions: *
  • Maximum version only: <=8.1.2
  • Minimum version only: >=9.3.2
  • Maximum and minimum version: >=9.3.2 <=8.1.2
ratingRecent
Rating from 0.0 to 1.0 (0.0 being the worst, 1.0 being the best) in the past 90 days
ratingNumRecent
Number of ratings for an app in the past 90 days, as in: how many votes were casted. 0 Means no ratings yet.
ratingOverall
Rating from 0.0 to 1.0 (0.0 being the worst, 1.0 being the best) of all time
ratingNumOverall
Number of ratings for an app overall, as in: how many votes were casted. 0 Means no ratings yet.
signature
A signature using SHA512 and the app’s certificate
signatureDigest
The hashing algorithm that is used to verify the signature
description
A full blown description containing Markdown
summary
A brief explanation what the app tries to do
isFeatured
Simple boolean flag which will be presented to the user as “hey take a look at this app”. Does not imply that it has been reviewed or we recommend it officially
categories
The string value is the category’s id attribute, see Get All Categories
changelog
The translated release changelog in Markdown. Can be empty for all languages
version
A semantic version without build metadata (e.g. 1.3.0, 1.2.1-alpha.1)

Register a New App

Before you can upload release you first need to register its app id. To do that use:

  • Url: POST /api/v1/apps

  • Authentication Basic, Token

  • Content-Type: application/json

  • Request body:

    • certificate: Your public certificate whose CN is equal to the app id, should be stored in ~/.nextcloud/certificates/APP_ID.cert where APP_ID is your app’s id

    • signature: A SHA512 signature over the app id using the app’s certificate, can be created using:

      echo -n "APP_ID" | openssl dgst -sha512 -sign ~/.nextcloud/certificates/APP_ID.key | openssl base64
      
    {
        "certificate": "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEojCCA4qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUx\r\nGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzEXMBUGA1UECgwOTmV4dGNsb3Vk\r\nIEdtYkgxNjA0BgNVBAMMLU5leHRjbG91ZCBDb2RlIFNpZ25pbmcgSW50ZXJtZWRp\r\nYXRlIEF1dGhvcml0eTAeFw0xNjA2MTIyMTA1MDZaFw00MTA2MDYyMTA1MDZaMGYx\r\nCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxEjAQBgNV\r\nBAcMCVN0dXR0Z2FydDEXMBUGA1UECgwOTmV4dGNsb3VkIEdtYkgxDTALBgNVBAMM\r\nBGNvcmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUxcrn2DC892IX\r\n8+dJjZVh9YeHF65n2ha886oeAizOuHBdWBfzqt+GoUYTOjqZF93HZMcwy0P+xyCf\r\nQqak5Ke9dybN06RXUuGP45k9UYBp03qzlUzCDalrkj+Jd30LqcSC1sjRTsfuhc+u\r\nvH1IBuBnf7SMUJUcoEffbmmpAPlEcLHxlUGlGnz0q1e8UFzjbEFj3JucMO4ys35F\r\nqZS4dhvCngQhRW3DaMlQLXEUL9k3kFV+BzlkPzVZEtSmk4HJujFCnZj1vMcjQBg\/\r\nBqq1HCmUB6tulnGcxUzt\/Z\/oSIgnuGyENeke077W3EyryINL7EIyD4Xp7sxLizTM\r\nFCFCjjH1AgMBAAGjggFDMIIBPzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIG\r\nQDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRp\r\nZmljYXRlMB0GA1UdDgQWBBQwc1H9AL8pRlW2e5SLCfPPqtqc0DCBpQYDVR0jBIGd\r\nMIGagBRt6m6qqTcsPIktFz79Ru7DnnjtdKF+pHwwejELMAkGA1UEBhMCREUxGzAZ\r\nBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzESMBAGA1UEBwwJU3R1dHRnYXJ0MRcw\r\nFQYDVQQKDA5OZXh0Y2xvdWQgR21iSDEhMB8GA1UEAwwYTmV4dGNsb3VkIFJvb3Qg\r\nQXV0aG9yaXR5ggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH\r\nAwEwDQYJKoZIhvcNAQELBQADggEBADZ6+HV\/+0NEH3nahTBFxO6nKyR\/VWigACH0\r\nnaV0ecTcoQwDjKDNNFr+4S1WlHdwITlnNabC7v9rZ\/6QvbkrOTuO9fOR6azp1EwW\r\n2pixWqj0Sb9\/dSIVRpSq+jpBE6JAiX44dSR7zoBxRB8DgVO2Afy0s80xEpr5JAzb\r\nNYuPS7M5UHdAv2dr16fDcDIvn+vk92KpNh1NTeZFjBbRVQ9DXrgkRGW34TK8uSLI\r\nYG6jnfJ6eJgTaO431ywWPXNg1mUMaT\/+QBOgB299QVCKQU+lcZWptQt+RdsJUm46\r\nNY\/nARy4Oi4uOe88SuWITj9KhrFmEvrUlgM8FvoXA1ldrR7KiEg=\r\n-----END CERTIFICATE-----",
        "signature": "65e613318107bceb131af5cf8b71e773b79e1a9476506f502c8e2017b52aba15"
    }
    
  • Example CURL request:

    curl -X POST -u "user:password" https://apps.nextcloud.com/api/v1/apps -H "Content-Type: application/json" -d '{"certificate": "certificate": "-----BEGIN CERTIFICATE-----\r\nMIIEojCCA4qgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwezELMAkGA1UEBhMCREUx\r\nGzAZBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzEXMBUGA1UECgwOTmV4dGNsb3Vk\r\nIEdtYkgxNjA0BgNVBAMMLU5leHRjbG91ZCBDb2RlIFNpZ25pbmcgSW50ZXJtZWRp\r\nYXRlIEF1dGhvcml0eTAeFw0xNjA2MTIyMTA1MDZaFw00MTA2MDYyMTA1MDZaMGYx\r\nCzAJBgNVBAYTAkRFMRswGQYDVQQIDBJCYWRlbi1XdWVydHRlbWJlcmcxEjAQBgNV\r\nBAcMCVN0dXR0Z2FydDEXMBUGA1UECgwOTmV4dGNsb3VkIEdtYkgxDTALBgNVBAMM\r\nBGNvcmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDUxcrn2DC892IX\r\n8+dJjZVh9YeHF65n2ha886oeAizOuHBdWBfzqt+GoUYTOjqZF93HZMcwy0P+xyCf\r\nQqak5Ke9dybN06RXUuGP45k9UYBp03qzlUzCDalrkj+Jd30LqcSC1sjRTsfuhc+u\r\nvH1IBuBnf7SMUJUcoEffbmmpAPlEcLHxlUGlGnz0q1e8UFzjbEFj3JucMO4ys35F\r\nqZS4dhvCngQhRW3DaMlQLXEUL9k3kFV+BzlkPzVZEtSmk4HJujFCnZj1vMcjQBg\/\r\nBqq1HCmUB6tulnGcxUzt\/Z\/oSIgnuGyENeke077W3EyryINL7EIyD4Xp7sxLizTM\r\nFCFCjjH1AgMBAAGjggFDMIIBPzAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIG\r\nQDAzBglghkgBhvhCAQ0EJhYkT3BlblNTTCBHZW5lcmF0ZWQgU2VydmVyIENlcnRp\r\nZmljYXRlMB0GA1UdDgQWBBQwc1H9AL8pRlW2e5SLCfPPqtqc0DCBpQYDVR0jBIGd\r\nMIGagBRt6m6qqTcsPIktFz79Ru7DnnjtdKF+pHwwejELMAkGA1UEBhMCREUxGzAZ\r\nBgNVBAgMEkJhZGVuLVd1ZXJ0dGVtYmVyZzESMBAGA1UEBwwJU3R1dHRnYXJ0MRcw\r\nFQYDVQQKDA5OZXh0Y2xvdWQgR21iSDEhMB8GA1UEAwwYTmV4dGNsb3VkIFJvb3Qg\r\nQXV0aG9yaXR5ggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH\r\nAwEwDQYJKoZIhvcNAQELBQADggEBADZ6+HV\/+0NEH3nahTBFxO6nKyR\/VWigACH0\r\nnaV0ecTcoQwDjKDNNFr+4S1WlHdwITlnNabC7v9rZ\/6QvbkrOTuO9fOR6azp1EwW\r\n2pixWqj0Sb9\/dSIVRpSq+jpBE6JAiX44dSR7zoBxRB8DgVO2Afy0s80xEpr5JAzb\r\nNYuPS7M5UHdAv2dr16fDcDIvn+vk92KpNh1NTeZFjBbRVQ9DXrgkRGW34TK8uSLI\r\nYG6jnfJ6eJgTaO431ywWPXNg1mUMaT\/+QBOgB299QVCKQU+lcZWptQt+RdsJUm46\r\nNY\/nARy4Oi4uOe88SuWITj9KhrFmEvrUlgM8FvoXA1ldrR7KiEg=\r\n-----END CERTIFICATE-----","signature": "65e613318107bceb131af5cf8b71e773b79e1a9476506f502c8e2017b52aba15"}'
    
  • Returns:

    • HTTP 201: If the app was not previously present and was registered successfully
    • HTTP 204: If the app has been updated (either owner or certificate change)
    • HTTP 400: If the app id contains invalid characters, the signature could not be validated or if the posted app certificate has been revoked
    • HTTP 401: If the user is not authenticated
    • HTTP 403: If the user is not authorized to update the app signature (only owners are allowed to do so)

You can also use this route to register a new certificate for an app if you are the app owner. However keep in mind that this will delete all previous app releases, since their signatures are now invalid and not installable anymore.

Find out more how to generate and request the certificate signature by following the App Developer Guide.

Note

DO NOT post your private key which is stored in the .key file. The private certificate needs to be stored securely. If you are unsure whether a file is a private certificate or the public one: your private certificate’s content starts with —–BEGIN PRIVATE KEY—–, whereas your public certificate’s content starts with —–BEGIN CERTIFICATE—–

Note

Keep in mind that we verify that the posted certificate and the signature are valid: the certificate needs to be signed by us and your app id signature must stem from the same certificate and match the expected result.

Publish a New App Release

The following request will create a new app release or update an existing release:

  • Url: POST /api/v1/apps/releases

  • Authentication Basic, Token

  • Content-Type: application/json

  • Request body:

    • download: An Https (Http is not allowed!) link to the archive packaged (maximum size: 20 Megabytes) as tar.gz, info.xml must be smaller than 512Kb

    • signature: A SHA512 signature over the archive using the app’s certificate, can be created using:

      openssl dgst -sha512 -sign ~/.nextcloud/certificates/APP_ID.key /path/to/app.tar.gz | openssl base64
      
    • nightly (Optional): If true this release will be stored as a nightly. All previous nightly releases will be deleted.

    {
        "download": "https://example.com/release.tar.gz",
        "signature": "65e613318107bceb131af5cf8b71e773b79e1a9476506f502c8e2017b52aba15",
        "nightly": false
    }
    
  • Example CURL request:

    curl -X POST -u "user:password" https://apps.nextcloud.com/api/v1/apps/releases -H "Content-Type: application/json" -d '{"download":"https://example.com/release.tar.gz", "signature": "65e613318107bceb131af5cf8b71e773b79e1a9476506f502c8e2017b52aba15"}'
    
  • Returns:

    • HTTP 200: If the app release was updated successfully
    • HTTP 201: If the app release was created successfully
    • HTTP 400: If the app release contains invalid data, is too large, is not registered yet, the signature could not be validated, the current app certificate has been revoked or could not be downloaded from the provided link
    • HTTP 401: If the user is not authenticated
    • HTTP 403: If the user is not authorized to create or update the app release

If there is no app with the given app id yet it will fail: you need to register your app id first. Then the info.xml file which lies in the compressed archive’s folder app-id/appinfo/info.xml is being parsed and validated. Afterwards the provided signature will be validated using the app’s certificate and the downloaded archive’s SHA512 checksum. The validated result is then saved in the database. Both owners and co-maintainers are allowed to upload new releases.

If the app release version is the latest version, everything is updated. If it’s not the latest release, only release relevant details are updated. This excludes the following info.xml elements:

  • name
  • summary
  • description
  • category
  • author
  • documentation
  • bugs
  • website
  • screenshot

For more information about validation and which info.xml fields are parsed, see App Metadata

Delete an App Release

Only app owners or co-maintainers are allowed to delete an app release. The owner is the user that pushes the first release of an app to the store.

  • Url: DELETE /api/v1/apps/{app-id}/releases/{app-version}
  • Url parameters:
  • app-id: app id, lower case ASCII characters and underscores are allowed
  • app-version: app version, semantic version, digits only
  • Authentication: Basic, Token

  • Authorization: App owners and co-maintainers

  • Example CURL request:

    curl -X DELETE https://apps.nextcloud.com/api/v1/apps/news/releases/9.0.0 -u "user:password"
    
  • Returns:

    • HTTP 204: If the app release was deleted successfully
    • HTTP 401: If the user is not authenticated
    • HTTP 403: If the user is not authorized to delete the app release
    • HTTP 404: If the app release could not be found

Delete a Nightly App Release

Only app owners or co-maintainers are allowed to delete a nightly app release. The owner is the user that pushes the first release of an app to the store.

  • Url: DELETE /api/v1/apps/{app-id}/releases/nightly/{app-version}
  • Url parameters:
  • app-id: app id, lower case ASCII characters and underscores are allowed
  • app-version: app version, semantic version, digits only
  • Authentication: Basic, Token

  • Authorization: App owners and co-maintainers

  • Example CURL request:

    curl -X DELETE https://apps.nextcloud.com/api/v1/apps/news/releases/nightly/9.0.0 -u "user:password"
    
  • Returns:

    • HTTP 204: If the app release was deleted successfully
    • HTTP 401: If the user is not authenticated
    • HTTP 403: If the user is not authorized to delete the app release
    • HTTP 404: If the app release could not be found

Delete an App

Only app owners are allowed to delete an app. The owner is the user that pushes the first release of an app to the store.

Deleting an app will also delete all releases which are associated with it.

  • Url: DELETE /api/v1/apps/{app-id}
  • Url parameters:
  • app-id: app id, lower case ASCII characters and underscores are allowed
  • Authentication: Basic, Token

  • Authorization: App owners

  • Example CURL request:

    curl -X DELETE https://apps.nextcloud.com/api/v1/apps/news -u "user:password"
    
  • Returns:

  • HTTP 204: If the app was deleted successfully
  • HTTP 401: If the user is not authenticated
  • HTTP 403: If the user is not authorized to delete the app
  • HTTP 404: If the app could not be found

Get All App Ratings

This route will return all rating comments.

  • Url: GET /api/v1/ratings.json

  • Authentication: None

  • Caching: ETag

  • Example CURL request:

    curl https://apps.nextcloud.com/api/v1/ratings.json -H 'If-None-Match: ""1-2016-09-03 17:11:38.772856+00:00""'
    
  • Returns: application/json

[
    {
        "rating": 1.0,
        "ratedAt": "2016-09-03T17:11:38.772856Z",
        "translations": {
            "en": {
                "comment": "I like it"
            }
        },
        "user": {
            "id": 1,
            "firstName": "Tom",
            "lastName": "Jones"
        },
        "app": "keeweb"
    }
]
translations
can contain 0 or any number of translated comments. If no comment is available for the currently chosen language, only the rating should be considered. Contains Markdown.
rating
range from 0.0 (worst) to 1.0 (best)