dappcdn api access

dAppCDN for Institutions

Latest versions, checksums and direct downloads of the official files, for universities, companies and IT departments, through an API key of their own.

Access is by request only: contact us and we will set up a key for your institution.

The official files, straight into your deployments

Universities, companies and IT departments keep hundreds of computers up to date. dAppCDN gives them what a person gets on our pages, without the pages: the latest version of every app, its checksums and a direct download of the official file, exactly as its developer released it, through an API key of their own.

What you get

  • The latest release of every app you need, by its name in our addresses (its slug).
  • For each file: its name, operating system, size, MD5, SHA-1 and SHA-256, and whether our antivirus scan passed.
  • Direct downloads, without the download page and its waiting time, from the same fast CDN as our site.
  • A key for your institution alone, limited to the apps and networks you choose.
  • Usage statistics of your key, on request: requests, downloads, and why a request was refused.

How it works

Every request carries your key in the Authorization header, never in the address. Three requests cover everything:

  • GET/api/institutions/v1/projects

    Every app your key reaches, each with its latest release.

  • GET/api/institutions/v1/projects/<slug>

    One app's latest release, with its files.

  • GET/api/institutions/v1/projects/<slug>/files/<file id>

    The file itself: a redirect to a short-lived download link. Every file in the answers above carries this address as download_url.

The answer for one app looks like this:

{
  "project": {
    "slug": "example-app",
    "name": "Example App",
    "url": "https://dappcdn.com/download/utilities/example-app",
    "release": {
      "id": "00000000-0000-4000-8000-000000000002",
      "version": "2.0.0",
      "files": [
        {
          "id": "00000000-0000-4000-8000-000000000001",
          "name": "example-app-2.0.0-setup.exe",
          "label": "Windows installer",
          "os": "windows",
          "size": 12582912,
          "hash": { "md5": "...", "sha1": "...", "sha256": "..." },
          "scanned": true,
          "available": true,
          "download_url": "https://dappcdn.com/api/institutions/v1/projects/example-app/files/00000000-0000-4000-8000-000000000001"
        }
      ]
    }
  }
}
  • The slug is the last part of an app's address on our site: /download/utilities/example-app is example-app.
  • os is one of windows, macos, linux, android, ios or other. A checksum we do not have is null.
  • A file that failed our antivirus scan is listed with "available": false and is never served.
  • A key can make around 300 requests a minute. Ask us if your deployments need more.
  • Errors answer with a JSON error and the usual status: 401 for a missing, wrong or expired key, 403 for an app, a network or an action the key does not allow, 404 for an unknown app or file, 429 when there are too many requests, 503 while downloads are paused (try again a few minutes later, as Retry-After says).

Getting a key: contact us

The API is not open: every key is issued by us, on request, one institution at a time. Write to us with the name of your institution, a contact person, what you would use the API for and the apps you need. If you want, tell us the networks (IP addresses or ranges) your requests will come from, and we will limit the key to them.

Keep the key on your servers and in your deployment tools only: not in a public repository, a script shared with others or a web page. If it is ever exposed, tell us and we will replace it at once.


Examples

Each example reads the latest release of an app, downloads one of its files and checks it against the published checksum. Replace example-app with the slug of the app you need and keep your key in DAPPCDN_KEY (or your tool's secret store).

curl and jq (bash)

#!/usr/bin/env bash
set -euo pipefail

# The latest release of one app
curl -fsS -H "Authorization: Bearer $DAPPCDN_KEY" \
  https://dappcdn.com/api/institutions/v1/projects/example-app

# Its Linux file, saved under its own name and checked against the published SHA-256
{ read -r NAME; read -r URL; read -r SHA256; } < <(
  curl -fsS -H "Authorization: Bearer $DAPPCDN_KEY" https://dappcdn.com/api/institutions/v1/projects/example-app \
    | jq -r '([.project.release.files[] | select(.os == "linux")][0] // {})
             | (.name // ""), (.download_url // ""), (.hash.sha256 // "")'
)
if [ -z "$URL" ]; then echo "No Linux file in the latest release" >&2; exit 1; fi
curl -fL -H "Authorization: Bearer $DAPPCDN_KEY" -o "$NAME" "$URL"
if [ -n "$SHA256" ]; then echo "$SHA256  $NAME" | sha256sum -c -; fi

PowerShell (Intune, Configuration Manager, PDQ Deploy)

# Intune (Win32 app), Configuration Manager, PDQ Deploy or a scheduled task
# Windows PowerShell 5.1 or PowerShell 7
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
$headers = @{ Authorization = "Bearer $env:DAPPCDN_KEY" }
$answer  = Invoke-RestMethod -Uri 'https://dappcdn.com/api/institutions/v1/projects/example-app' -Headers $headers
$file    = $answer.project.release.files | Where-Object { $_.os -eq 'windows' } | Select-Object -First 1
if (-not $file) { throw 'No Windows file in the latest release' }

Write-Output "Latest version: $($answer.project.release.version)"
Invoke-WebRequest -Uri $file.download_url -Headers $headers -OutFile $file.name -UseBasicParsing

if ($file.hash.sha256 -and (Get-FileHash $file.name -Algorithm SHA256).Hash -ne $file.hash.sha256) {
    throw "Checksum mismatch for $($file.name)"
}

AutoPkg (Munki, Jamf Pro)

A recipe for AutoPkg 2.3 or newer, with only its core processors. Add your own processors after the download to import it into Munki or Jamf Pro, as with any other download recipe. AutoPkg writes the variables of a run, the key among them, to its receipts on the Mac that runs it: keep that machine's AutoPkg cache private.

# ExampleApp.download.recipe.yaml
# DAPPCDN_KEY comes from your AutoPkg preferences or the command line, never from the recipe:
#   defaults write com.github.autopkg DAPPCDN_KEY "<key>"
#   autopkg run ExampleApp.download.recipe.yaml -k DAPPCDN_KEY="<key>"
Description: Downloads the latest macOS release of Example App from dAppCDN.
Identifier: com.example.autopkg.download.ExampleApp
MinimumVersion: '2.3'
Input:
  NAME: ExampleApp
  SLUG: example-app
Process:
  - Processor: URLTextSearcher
    Arguments:
      url: https://dappcdn.com/api/institutions/v1/projects/%SLUG%
      request_headers:
        Authorization: Bearer %DAPPCDN_KEY%
      re_pattern: '"version":"(?P<version>[^"]+)"'
  - Processor: URLTextSearcher
    Arguments:
      url: https://dappcdn.com/api/institutions/v1/projects/%SLUG%
      request_headers:
        Authorization: Bearer %DAPPCDN_KEY%
      re_pattern: '"name":"[^"]+\.dmg".*?"download_url":"(?P<download_url>[^"]+)"'
  - Processor: URLDownloader
    Arguments:
      url: '%download_url%'
      request_headers:
        Authorization: Bearer %DAPPCDN_KEY%
      filename: '%NAME%-%version%.dmg'
  - Processor: EndOfCheckPhase

Ansible

# dappcdn_key: kept in Ansible Vault
- name: Read the latest release of Example App
  ansible.builtin.uri:
    url: https://dappcdn.com/api/institutions/v1/projects/example-app
    headers:
      Authorization: "Bearer {{ dappcdn_key }}"
    return_content: true
  register: dappcdn

- name: Pick its Linux file
  ansible.builtin.set_fact:
    dappcdn_file: "{{ dappcdn.json.project.release.files | selectattr('os', 'equalto', 'linux') | first }}"

- name: See whether this version is already there
  ansible.builtin.stat:
    path: "/opt/packages/{{ dappcdn_file.name }}"
    checksum_algorithm: sha256
  register: dappcdn_local

# The key goes to dAppCDN only: get_url would also send it to the CDN behind the redirect
- name: Get the file's short-lived download link
  when: not (dappcdn_local.stat.exists and dappcdn_local.stat.checksum == dappcdn_file.hash.sha256)
  ansible.builtin.uri:
    url: "{{ dappcdn_file.download_url }}"
    headers:
      Authorization: "Bearer {{ dappcdn_key }}"
    follow_redirects: none
    status_code: 302
  register: dappcdn_link

- name: Download it, checked against the published SHA-256
  when: dappcdn_link is not skipped
  ansible.builtin.get_url:
    url: "{{ dappcdn_link.location }}"
    dest: "/opt/packages/{{ dappcdn_file.name }}"
    checksum: "{{ ('sha256:' + dappcdn_file.hash.sha256) if dappcdn_file.hash.sha256 else omit }}"

Using another tool? Any tool that can send an HTTP header works the same way. Write to us and we will help you set it up.