Skip to main content
Fermion offers an easy-to-use API for creating and managing downloadable digital products. This guide will help you upload and publish ZIP files via API step by step.

Overview

With Fermion’s Downloadable Products API, you can:
  • Create downloadable product entries through code
  • Securely upload files to our cloud storage
  • Process and prepare files for distribution
  • Update product metadata and descriptions
  • Set up and edit pricing plans
  • Manage multiple versions of any downloadable product

Prerequisites

Before you begin, make sure you have:
  • A valid Fermion API key
  • A ZIP file ready for upload
  • Basic familiarity with HTTP requests and file uploads
1

Create a Downloadable Product

Create a new downloadable product using the create-downloadable-product endpoint.Refer to the create-downloadable-product endpoint for call details.Sample Response:
{
	"status": "ok",
	"data": {
		"fermionDigitalProductId": "prod_abc123xyz",
		"slug": "xyz789"
	}
}
Save the slug value—it’s a unique, URL-friendly ID you’ll use for all later API calls.
2

Get a Presigned Upload URL

See the get-presigned-url-for-downloadable-product-upload for details.Sample Response:
{
	"status": "ok",
	"data": {
		"r2KeyForOriginalDownloadableProduct": "private-cached-downloadable-unencrypted/prod_abc123xyz/file_unique_id",
		"presignedUrl": "https://storage.example.com/upload?signature=..."
	}
}
The presigned upload URL will expire in 1 hour. Be sure to upload your file before then. If it expires, just request a new upload URL.
Key Points:
  • Save r2KeyForOriginalDownloadableProduct—you’ll need it next
  • The upload link is one-time and time-limited for security
  • Requesting a new URL allows you to upload a new version
3

Upload the File via Presigned URL

Upload your file using a HTTP PUT request to the URL from Step 2.
curl -X PUT \
  -H "Content-Type: application/zip" \
  --data-binary @your-product.zip \
  "https://storage.example.com/upload?signature=..."
Use the HTTP PUT method (not POST) and make sure Content-Type is set to application/zip for correct uploads.
4

Process the Uploaded Product

After uploading your file, trigger processing to prepare it for distribution.See the process-uploaded-downloadable-product.Sample Request Body:
{
	"productSlug": "xyz789",
	"r2KeyForOriginalDownloadableProduct": "private-cached-downloadable-unencrypted/prod_abc123xyz/file_unique_id"
}
Sample Response:
{
	"status": "ok",
	"data": {
		"downloadableProductVersionIndex": 0
	}
}
What Processing Does:
  1. Downloads your file from storage
  2. Validates the file format and integrity
  3. Prepares the file for secure distribution
  4. Logs version metadata to your product
Save the downloadableProductVersionIndex—you’ll need it to activate (publish) this version.
5

Update Product Metadata (Optional)

See API docs: update-downloadable-product-metadataSample Request Body:
{
	"productSlug": "xyz789",
	"title": "Premium Design Templates Pack",
	"shortDescription": "Professional templates for web and print",
	"longDescription": "This comprehensive pack includes everything you need to create stunning designs...",
	"activeVersionIndex": 0
}
Field Breakdown:
  • title (optional): Product display title
  • shortDescription (optional): Summary for listings
  • longDescription (optional): Main description on product page
  • activeVersionIndex (optional): Which uploaded version customers see
Important: Set activeVersionIndex to the version index returned from Step 4 to activate your upload. Only processed downloadable product versions (uploaded-and-processed) can be marked active.
6

Add Pricing (Optional)

To set up paid access, use the digital product pricing API.See docs: create-custom-pricing-plan-for-a-product
7

Publish & Share

After completing the above, your downloadable product is ready to be published by setting it to “Active.”

Complete Example: JavaScript/Node.js Workflow

Below is a full downloadable product upload example using Node.js:
const API_KEY = 'your-api-key'
const BASE_URL = 'https://your-school.fermion.app/api'

// Step 1: Create the downloadable product
const createResponse = await fetch(`${BASE_URL}/public/create-downloadable-product`, {
	method: 'POST',
	headers: {
		'fermion-api-key': API_KEY,
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({
		downloadableProductName: 'My Premium Templates',
		shortDescription: 'Professional design templates',
		status: 'Draft'
	})
})

const { slug, fermionDigitalProductId } = (await createResponse.json()).data

// Step 2: Request presigned upload URL
const uploadUrlResponse = await fetch(`${BASE_URL}/public/get-presigned-url-for-downloadable-product-upload`, {
	method: 'POST',
	headers: {
		'fermion-api-key': API_KEY,
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({ productSlug: slug })
})

const { presignedUrl, r2KeyForOriginalDownloadableProduct } = (await uploadUrlResponse.json()).data

// Step 3: Upload the file
const fileBuffer = fs.readFileSync('./my-product.zip')
await fetch(presignedUrl, {
	method: 'PUT',
	headers: { 'Content-Type': 'application/zip' },
	body: fileBuffer
})

// Step 4: Process the uploaded file
const processResponse = await fetch(`${BASE_URL}/public/process-uploaded-downloadable-product`, {
	method: 'POST',
	headers: {
		'fermion-api-key': API_KEY,
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({
		productSlug: slug,
		r2KeyForOriginalDownloadableProduct
	})
})

const { downloadableProductVersionIndex } = (await processResponse.json()).data

// Step 5: Update metadata and activate version
await fetch(`${BASE_URL}/public/update-downloadable-product-metadata`, {
	method: 'POST',
	headers: {
		'fermion-api-key': API_KEY,
		'Content-Type': 'application/json'
	},
	body: JSON.stringify({
		productSlug: slug,
		title: 'My Premium Templates',
		longDescription: 'This pack includes professional templates...',
		activeVersionIndex: downloadableProductVersionIndex
	})
})

console.log(`Downloadable product created successfully! Product ID: ${fermionDigitalProductId}`)

Managing Multiple Product Versions

You can upload new versions (such as updates or corrections) for the same downloadable product:
1

Get New Presigned Upload URL

Call get-presigned-url-for-downloadable-product-upload again to get a fresh upload URL.
2

Upload New File

Upload your new file via the new URL.
3

Process the Upload

Process the new version.
4

Update Version Index

Update activeVersionIndex via the metadata API to switch to the new version.
Don’t delete past versions—you can switch between them any time by changing activeVersionIndex.

Getting Help

If you get stuck or have an edge-case issue:
  • See the API Reference for endpoint details
  • Check the Webhooks Guide to track product purchases
  • For product-specific issues, contact support and include your fermionDigitalProductId