---
title: "Create a digital product"
description: "Make a Shopify product or one of its variants a digital product, as the Products page's Add does: give shopify_product_id (whole product) or shopify_variant_id (one variant; add shopify_product_id too unless Filemonk alr"
url: https://docs.filemonk.io/v2/api-reference/digital-products/create-a-digital-product/
api: "API v2 reference"
method: POST
path: "/digital_products"
---

# Create a digital product

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

Make a Shopify product or one of its variants a digital product, as the Products page's Add does: give shopify_product_id (whole product) or shopify_variant_id (one variant; add shopify_product_id too unless Filemonk already knows the variant), the files to deliver as files: [{id, folder}], and optionally delivery.message, delivery.attach_to_every_order, preorder {enabled, launch_at, email {subject, heading, description}} (enabling a pre-order needs launch_at and delivery.message) and update_email {subject, body}.

**Note:** preorder.enabled: true needs preorder.launch_at at least two hours ahead and a delivery.message (422 naming the missing field otherwise). 404 when Shopify has no such product or variant in this store. 409 when the product or variant already is a digital product (PATCH it instead). Buyers of existing orders are not emailed; use [`POST /digital_products/:id/notify_buyers`](https://docs.filemonk.io/v2/api-reference/digital-products/notify-buyers-of-a-digital-product/).

## Request body

- `shopify_product_id` (string): e.g. `gid://shopify/Product/9642107044135`
- `shopify_variant_id` (any)
- `files` (array of objects)
  - `id` (string): e.g. `e2b7727e-45ad-42b7-b842-cc4615205b10`
  - `folder` (string): e.g. `Extras`
- `delivery` (object)
  - `message` (string): e.g. `Thanks for your order! Your files are below.`
  - `attach_to_every_order` (boolean): e.g. `false`
- `preorder` (any)
- `update_email` (any)

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

## Examples

### Deliver files for a whole product

```sh
curl -X POST "https://app.filemonk.io/api/v2/external/digital_products" \
  -H "X-Auth-Token: $FILEMONK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shopify_product_id": "gid://shopify/Product/9642107044135",
    "files": [
      {
        "id": "e2b7727e-45ad-42b7-b842-cc4615205b10",
        "folder": "Extras"
      }
    ],
    "delivery": {
      "message": "Thanks for your order! Your files are below.",
      "attach_to_every_order": false
    }
  }'
```

Response:

```json
{
  "id": "7ea3c05d-6f29-42b6-b24f-43260caeaa32",
  "scope": "product",
  "shopify_product_id": "gid://shopify/Product/9642107044135",
  "shopify_variant_id": null,
  "title": "Watercolour Course",
  "variant_title": null,
  "sku": null,
  "exists_on_shopify": null,
  "files": [
    {
      "id": "7ea42f2a-6dbe-459c-b8a4-27b0eb823e52",
      "name": "price-list.csv",
      "type": "file",
      "byte_size": 100634,
      "folder": null
    },
    {
      "id": "96fbe30b-c819-4cb8-9666-814c0c8853f1",
      "name": "Beginner's Guide.pdf",
      "type": "file",
      "byte_size": 116711,
      "folder": null
    }
  ],
  "folders": [],
  "delivery": {
    "message": null,
    "attach_to_every_order": false
  },
  "preorder": {
    "enabled": false,
    "launch_at": null,
    "released": true,
    "email": {
      "subject": null,
      "heading": null,
      "description": null
    }
  },
  "update_email": {
    "subject": null,
    "body": null
  },
  "orders_count": 46,
  "created_at": "2025-05-31T13:37:52Z",
  "updated_at": "2025-05-31T13:37:52Z"
}
```

### Deliver files for one variant

```sh
curl -X POST "https://app.filemonk.io/api/v2/external/digital_products" \
  -H "X-Auth-Token: $FILEMONK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shopify_product_id": "gid://shopify/Product/9642107207975",
    "shopify_variant_id": "gid://shopify/ProductVariant/49417715843367",
    "files": [
      {
        "id": "e2b7727e-45ad-42b7-b842-cc4615205b10"
      }
    ]
  }'
```

Response:

```json
{
  "id": "7ea3c05d-6f29-42b6-b24f-43260caeaa32",
  "scope": "variant",
  "shopify_product_id": "gid://shopify/Product/9642107207975",
  "shopify_variant_id": "gid://shopify/ProductVariant/49417715843367",
  "title": "Watercolour Course",
  "variant_title": "xs / blue / water",
  "sku": null,
  "exists_on_shopify": null,
  "files": [
    {
      "id": "7ea42f2a-6dbe-459c-b8a4-27b0eb823e52",
      "name": "price-list.csv",
      "type": "file",
      "byte_size": 100634,
      "folder": null
    },
    {
      "id": "96fbe30b-c819-4cb8-9666-814c0c8853f1",
      "name": "Beginner's Guide.pdf",
      "type": "file",
      "byte_size": 116711,
      "folder": null
    }
  ],
  "folders": [],
  "delivery": {
    "message": null,
    "attach_to_every_order": false
  },
  "preorder": {
    "enabled": false,
    "launch_at": null,
    "released": true,
    "email": {
      "subject": null,
      "heading": null,
      "description": null
    }
  },
  "update_email": {
    "subject": null,
    "body": null
  },
  "orders_count": 0,
  "created_at": "2025-05-31T13:37:52Z",
  "updated_at": "2025-05-31T13:37:52Z"
}
```

### Sell it as a pre-order

launch_at must be at least two hours ahead, and a pre-order needs delivery.message.

```sh
curl -X POST "https://app.filemonk.io/api/v2/external/digital_products" \
  -H "X-Auth-Token: $FILEMONK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "shopify_product_id": "gid://shopify/Product/9642107044135",
    "files": [
      {
        "id": "e2b7727e-45ad-42b7-b842-cc4615205b10"
      }
    ],
    "delivery": {
      "message": "Thanks for pre-ordering! Your files arrive on launch day."
    },
    "preorder": {
      "enabled": true,
      "launch_at": "2026-12-01T09:00:00Z"
    }
  }'
```

Response:

```json
{
  "id": "7ea3c05d-6f29-42b6-b24f-43260caeaa32",
  "scope": "product",
  "shopify_product_id": "gid://shopify/Product/9642107044135",
  "shopify_variant_id": null,
  "title": "Watercolour Course",
  "variant_title": null,
  "sku": null,
  "exists_on_shopify": null,
  "files": [
    {
      "id": "7ea42f2a-6dbe-459c-b8a4-27b0eb823e52",
      "name": "price-list.csv",
      "type": "file",
      "byte_size": 100634,
      "folder": null
    },
    {
      "id": "96fbe30b-c819-4cb8-9666-814c0c8853f1",
      "name": "Beginner's Guide.pdf",
      "type": "file",
      "byte_size": 116711,
      "folder": null
    }
  ],
  "folders": [],
  "delivery": {
    "message": "Thanks for pre-ordering! Your files arrive on launch day.",
    "attach_to_every_order": false
  },
  "preorder": {
    "enabled": true,
    "launch_at": "2026-12-01T09:00:00Z",
    "released": false,
    "email": {
      "subject": null,
      "heading": null,
      "description": null
    }
  },
  "update_email": {
    "subject": null,
    "body": null
  },
  "orders_count": 0,
  "created_at": "2025-05-31T13:37:52Z",
  "updated_at": "2025-05-31T13:37:52Z"
}
```

## 200

Success: the resource already existed; here it is.

## 201

Created: the new resource.

```json
{
  "id": "7ea3c05d-6f29-42b6-b24f-43260caeaa32",
  "scope": "product",
  "shopify_product_id": "gid://shopify/Product/9642107044135",
  "shopify_variant_id": null,
  "title": "Watercolour Course",
  "variant_title": null,
  "sku": null,
  "exists_on_shopify": null,
  "files": [
    {
      "id": "7ea42f2a-6dbe-459c-b8a4-27b0eb823e52",
      "name": "price-list.csv",
      "type": "file",
      "byte_size": 100634,
      "folder": null
    },
    {
      "id": "96fbe30b-c819-4cb8-9666-814c0c8853f1",
      "name": "Beginner's Guide.pdf",
      "type": "file",
      "byte_size": 116711,
      "folder": null
    }
  ],
  "folders": [],
  "delivery": {
    "message": null,
    "attach_to_every_order": false
  },
  "preorder": {
    "enabled": false,
    "launch_at": null,
    "released": true,
    "email": {
      "subject": null,
      "heading": null,
      "description": null
    }
  },
  "update_email": {
    "subject": null,
    "body": null
  },
  "orders_count": 46,
  "created_at": "2025-05-31T13:37:52Z",
  "updated_at": "2025-05-31T13:37:52Z"
}
```

## 401

Missing or invalid API key.

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

## 404

The resource does not exist for this shop, or the action path is not registered.

```json
{
  "errors": [
    "Order not found: c3d4e5f6-7a8b-4c9d-8e0f-1a2b3c4d5e6f"
  ]
}
```

## 409

The request conflicts with the current state (an order Shopify is not ready to fulfil, a digital product that already exists). Nothing was changed; read the message, don't retry blindly.

```json
{
  "errors": [
    "This product already has a digital product"
  ]
}
```

## 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)."
}
```

