---
title: "Create a licence"
description: "Add licence keys to the pool (keys, one string each), under a tag when given, as the Licence keys page's Add keys does. Orders still waiting for a key from that pool are served right after."
url: https://docs.filemonk.io/v2/api-reference/licences/create-a-licence/
api: "API v2 reference"
method: POST
path: "/licences"
---

# Create a licence

`POST https://app.filemonk.io/api/v2/external/licences`

Add licence keys to the pool (keys, one string each), under a tag when given, as the Licence keys page's Add keys does. Orders still waiting for a key from that pool are served right after.

**Note:** Keys already in the shop (and repeats within the request) are skipped and counted in skipped_duplicates; send allow_duplicates: true to add them anyway. Keys are deleted on the Licence keys page (or [`DELETE /licences/:id`](https://docs.filemonk.io/v2/api-reference/licences/delete-a-licence/) over REST).

## Request body

- `keys` (array of strings, required)
- `allow_duplicates` (boolean)
- `tag` (string): e.g. `ebook-2026`

Rate limit: this call costs 2 points ([rate limits](https://docs.filemonk.io/v2/errors-and-rate-limits/)).

## Examples

### Add keys to a pool

```sh
curl -X POST "https://app.filemonk.io/api/v2/external/licences" \
  -H "X-Auth-Token: $FILEMONK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keys": [
      "ABCD-EFGH-IJKL-0001",
      "ABCD-EFGH-IJKL-0002"
    ],
    "tag": "ebook-2026"
  }'
```

Response:

```json
{
  "created": 2,
  "skipped_duplicates": 0,
  "tag": {
    "name": "ebook-2026",
    "virtual": false,
    "licences": {
      "total": 2,
      "pending": 2,
      "assigned": 0,
      "used": 0
    },
    "digital_products": []
  }
}
```

### Add a key that is already in the shop

Without allow_duplicates the key would be skipped and counted in skipped_duplicates.

```sh
curl -X POST "https://app.filemonk.io/api/v2/external/licences" \
  -H "X-Auth-Token: $FILEMONK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "keys": [
      "ABCD-EFGH-IJKL-0001"
    ],
    "tag": "ebook-2026",
    "allow_duplicates": true
  }'
```

Response:

```json
{
  "created": 1,
  "skipped_duplicates": 0,
  "tag": {
    "name": "ebook-2026",
    "virtual": false,
    "licences": {
      "total": 3,
      "pending": 3,
      "assigned": 0,
      "used": 0
    },
    "digital_products": []
  }
}
```

## 200

Success: the resource already existed; here it is.

## 201

Created: the new resource.

```json
{
  "created": 2,
  "skipped_duplicates": 0,
  "tag": {
    "name": "ebook-2026",
    "virtual": false,
    "licences": {
      "total": 2,
      "pending": 2,
      "assigned": 0,
      "used": 0
    },
    "digital_products": []
  }
}
```

## 401

Missing or invalid API key.

```json
{
  "errors": [
    "Invalid API key"
  ]
}
```

## 422

The request failed validation, or sent a key the action does not take (`code: &quot;unknown_parameters&quot;` with `unknown` and `accepted`). Nothing was saved.

```json
{
  "errors": [
    "access.download_limit_count must be an integer of at least 0"
  ],
  "field_errors": {
    "access.download_limit_count": [
      "must be an integer of at least 0"
    ]
  }
}
```

## 429

Rate limited. Cost-weighted per API key, shared with API v1: a read costs 1 point, a write 2, 40 points per fixed 60-second window. Every response carries `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` (Unix time the window ends); a 429 adds `Retry-After` (seconds), `retry_after`, `retryable: true` and a `next_step` in the body. A 429 did nothing: wait `retry_after` seconds, then send the same request again. The budget is per key, so every tool or script using the key shares it; prefer one list call with `per_page` over many single reads.

```json
{
  "errors": [
    "You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
  ],
  "code": "rate_limited",
  "retry_after": 12,
  "error": "Rate limit exceeded",
  "message": "You have exceeded the rate limit of 40 points per 60 seconds. Read requests cost 1 point(s) and write requests cost 2 point(s). Please retry after 12 second(s)."
}
```

