---
url: https://docs.sunlicense.com/guide/protected-files.md
---
# Protected files

Keep part of your product with SunLicense: a rules file, a model, a map pack, the paid half of your content. Your app downloads it at run time, and **only a valid license gets it**. A cracked copy with the license check patched out still has nothing to load.

Protected files are on the **Standard** [plan](/guide/plans), with 100 MB for all your products' protected files together.

## Upload a file

Each product has its own files, by name (letters, digits, dots, dashes and underscores, like `rules.dat`). Uploading the same name again replaces the file; apps get the new one on their next download.

* **CLI:** `sunlicense files push rules.dat --product acme-editor`, and `sunlicense files list --product acme-editor`.
* **Dashboard:** the product's **Setup** tab, **Protected files**.
* **API:** `POST /api/v1/distribution/products/{productId}/protected-files` with `{"name": "rules.dat", "size": 1234}` returns an upload URL; `PUT` the bytes to it with the headers it lists, then `POST …/protected-files/{fileId}/complete`. `GET …/protected-files` lists them, `DELETE …/protected-files/{fileId}` removes one.

## Download it from your app

With the SDK (Java shown; every SDK has the same call):

```java
byte[] rules = client.protectedFile("rules.dat");
```

Or over HTTP, with the same API key your app validates with:

```http
GET https://api.sunlicense.com/api/v2/protected-files/acme-editor/rules.dat
Authorization: Bearer slk_…
X-License-Key: AX8P-…
X-Fingerprint: <this machine's fingerprint>
```

| Answer | Means |
|---|---|
| `200` | The file. `ETag` and `X-Content-SHA256` carry its SHA-256. |
| `304` | You sent `If-None-Match` with the current `ETag`: your cached copy is current (the license was still checked). |
| `403 license_not_allowed` | The license is unknown, of another product, suspended, revoked, expired, or its customer is blocked. |
| `403 protected_files_unavailable` | Your plan doesn't include protected files right now. |
| `404 protected_file_not_found` | No file of that name. |
| `429` | This license downloaded too often; wait for `Retry-After` seconds. |
| `503` | SunLicense couldn't check the license just now: keep using a copy you already have and try again later. |

The license is checked at every download, never cached, so suspending or revoking a license stops its downloads at once. Each license can download about 120 times an hour (20 at once).

## What it does and doesn't protect

A holder of a valid license can still save the file once it's downloaded. Protected files keep the file away from people without a license and from copies whose license was suspended; pair them with [download watermarks](/guide/downloads#how-the-license-gets-into-the-file) so a leaked copy names its buyer.
