Behio Storefront SDK
Customer

Digital Downloads

Deliver purchased digital files (PDF, MP3, e-book) and let customers download them

Overview

A product can carry one or more digital assets (PDF, MP3, e-book, software) that the buyer receives automatically once the order is paid. When an order transitions to paid (an online gateway confirms payment, an admin marks it paid, or a gift card fully covers the total), Behio creates a download grant for every active digital asset of the purchased products. Unpaid orders (cash on delivery, bank transfer before payment) never receive grants.

Grants enforce an optional per-customer download limit (maxDownloads) and expiry (expiresAfterDays, counted from the grant). Files are served through short-lived signed URLs; the limit and expiry are enforced server-side, so a leaked URL cannot be reused past its budget.

List the customer's downloads

Requires customer authentication. Returns every grant across all the customer's orders:

const { data } = await client.customer.getDownloads();
// {
//   items: [{
//     id: string,
//     orderId: string | null,
//     fileName: string,
//     productName: string | null,   // localized, for display
//     productSlug: string | null,
//     fileSize: number,             // bytes
//     mimeType: string,
//     version: string | null,
//     downloadCount: number,
//     maxDownloads: number | null,       // null = unlimited
//     remainingDownloads: number | null, // null = unlimited
//     lastDownloadAt: number | null,
//     expiresAt: number | null,          // epoch ms, null = never
//     isExpired: boolean,
//     isMaxedOut: boolean,
//     createdAt: number,
//   }]
// }

Get a signed download URL

Mint a short-lived (15 min) signed URL for one grant. This counts against the download budget and is rejected (403) once the grant is expired or maxed out:

const { data, error } = await client.customer.getDownloadUrl(downloadId);
// data: { url, fileName, mimeType, fileSize, remainingDownloads, expiresAt }
if (data) window.open(data.url, "_blank");

Check isExpired / isMaxedOut on the grant to disable the download button before calling.

Order detail

Paid order details carry the same grants inline, so you can show a download section on the order / confirmation page without a second call:

const { data: order } = await client.orders.get(orderNumber);
order?.downloads; // DigitalDownload[], empty for unpaid or physical-only orders

Product badge

The product detail exposes isDigital: boolean, true when the product has at least one active digital asset. Use it to render an "instant delivery" badge on the PDP.

Guest orders

A guest who verified an order via the order-access flow can mint a download URL with the order-access token, scoped to that one order:

const { data } = await client.orders.getAccessDownloadUrl(accessToken, downloadId);

Admin

Merchants attach digital assets to a product in the admin, or via MCP (eshop-digital-asset-create, eshop-digital-assets-list, eshop-digital-asset-update, eshop-digital-asset-delete) with fileUrl (an R2/S3 object), fileSize, mimeType, and optional maxDownloads + expiresAfterDays.

On this page