π§ Connect Big Digital Downloads to CRM, ERP or App (Public API/Webhooks)
These features are available from the Growth plan and above.
If you sell digital products on Shopify, your order data, license keys, and download analytics probably need to live in more than one place. Your CRM needs to know when someone buys an ebook. Your license server needs to validate keys when customers activate your software. Your support team needs to resend download emails or reset download limits without opening the admin every time.
Big Digital Downloads' Public API and Webhooks make all of this possible. The API gives you 21 endpoints to read orders and products, manage license keys from creation to assignment, upload and delete files, create secure download links, toggle download access, resend delivery emails, and pull download statistics. Webhooks push real-time notifications to your server whenever an order is purchased, a delivery email is sent, or a file is downloaded.
Both features are currently in Beta.
The full interactive API reference with all schemas and response examples is at https://islandcloud.co/public-api/docs
What can you build with the Big Digital Downloads API?
Here are real integration scenarios that merchants are building right now:
Build a license validation server for your software. When a customer buys your desktop app or plugin, Big DD assigns a license key. Your software calls the Validate endpoint on launch to check whether the key is valid and assigned. No third-party license service needed.
Bulk-import license keys from your key generator. Use the batch endpoint to push up to 5,000 keys per request, tagged by product or batch name, with automatic deduplication. Your key generation pipeline runs on its own schedule, and Big DD's inventory stays in sync.
Sync every order to HubSpot, Salesforce, or any CRM. When a customer purchases a digital product, a webhook fires instantly with the full order data (customer name, email, products, price, financial status). Your CRM creates or updates the contact automatically with no manual data entry.
Automate workflows with Zapier or Make without code. Point a Big DD webhook to your Zapier or Make webhook URL. Every order or download event becomes a trigger. Send a Slack notification when someone buys, add a row to Google Sheets, trigger a drip sequence in Klaviyo, or create a task in Asana.
Build a custom download portal. Use the API to list a customer's orders and their download history, generate secure download links with optional limits and PDF watermarking, and manage access programmatically. Your frontend calls your backend, which calls the Big DD API.
Resend delivery emails or reset download limits from your support dashboard. Instead of opening the Big DD admin for every support ticket, call the API from your helpdesk tool. One endpoint resends the email (optionally to a new address), another resets the download counter.
Feed download analytics into your BI tool. Pull aggregated download counts, bandwidth usage, and top-downloaded files for any time window. Export to your data warehouse or Google Sheets for custom dashboards.
Protect your PDFs with automatic watermarking. When creating download links via API, enable PDF stamping to watermark every PDF with custom text like the customer's name or order number. This works automatically for all PDFs in the link.
Authentication
Every API request requires a Bearer token generated from your Big Digital Downloads admin. Tokens have full read and write access to your shop's orders, products, license keys, and files. Treat them like passwords: do not commit them to version control or share them in public channels.
How to generate your API token
In your Shopify admin, open the Big Digital Downloads app.
Go to Settings > Public API.
Click Generate token.
Give your token a descriptive name so you can identify it later, for example "CRM sync", "License server", or "Zapier".
Click Generate.

Big Digital Downloads shows you the full token one time only. Copy it immediately and store it in a secure location like a password manager or your server's environment variables.
You can revoke any token at any time from the same page. Revoking a token immediately stops all API requests using it.
Using your token
Include the token in the Authorization header of every API request:
Example with curl:
If the token is missing or invalid, the API returns 401.
API endpoints
Base URL: https://islandcloud.co
The API is organized into 7 areas: digital products, orders, license keys, files, download links, download statistics, and customer downloads.
Digital products
List digital products
GET /public-api/v1/digital-products
Returns all digital products in your shop. Use this to discover product IDs, delivery types, access modes, download limits, and linked files before making other API calls.
Query parameters:
limit (optional, 1-100): number of results per page.
cursor (optional): pagination cursor from a previous response.
include_archived (optional, true or false): include archived products. Defaults to false.
q (optional, max 120 characters): search by product name.
include (optional): pass product to attach the Shopify product title and image. This costs an extra GraphQL call per product, so use it only when you need it.
sort (optional): -id (default, newest first), id (oldest first), created_at, -created_at.
Example request:
Example response (shortened):
Understanding key digital product fields
delivering_type determines how files reach the customer:
REGULAR means all customers receive the same files. This is the most common mode for ebooks, templates, presets, music, and any product where every buyer gets the same download.
UNIQUE means each customer gets different files. You assign specific files to each order line via the API or the admin. Useful for personalized content, custom artwork, or one-of-a-kind assets.
SCHEDULED means files are delivered on a specific future date. Use this for pre-orders or timed releases where all buyers receive the files simultaneously on a set date.
access determines what the customer receives:
FILE means the customer gets downloadable files only.
LICENSE_KEY means the customer receives a license key only, no files.
FILE_WITH_LICENCE_KEY means the customer gets both files and a license key.
max_downloads is the maximum number of times each customer can download the files. 0 or null means unlimited.
download_in is the number of days the download link stays valid after purchase. 0 or null means no expiry.
files is the list of files attached to this product. Each file includes its ID, name, size, MIME type, and encryption status.
Get a single digital product
GET /public-api/v1/digital-products/{id}
Returns the full details of one product, including the same fields as the list endpoint.
Update download limits
PUT /public-api/v1/digital-products/{id}/limits
Changes the download limit and link expiry for a product. This is the only write operation on digital products. All other product configuration (name, files, delivery type) is managed from the admin.
Body:
Set max_downloads to 0 or null for unlimited. Set download_in to 0 or null for no expiry. Maximum values: 1,000,000 downloads, 100,000 days.
Example: give customers more downloads after a product update:
Orders
List orders
GET /public-api/v1/orders
Returns digital orders for your shop. This is the endpoint you use for CRM syncs, reporting exports, and custom order dashboards.
Query parameters:
limit (optional, 1-100): results per page.
cursor (optional): pagination cursor.
created_after (optional, ISO 8601): only orders created on or after this date (inclusive).
created_before (optional, ISO 8601): only orders created before this date (exclusive).
financial_status (optional, array): AUTHORIZED, EXPIRED, PAID, PARTIALLY_PAID, PARTIALLY_REFUNDED, PENDING, REFUNDED, VOIDED.
digital_product_id (optional, array of IDs): filter by one or more digital products.
customer_email (optional): filter by exact customer email.
q (optional, max 120 characters): search by order name (e.g. #1001).
include (optional, array): product attaches Shopify product title and image to each line. downloads attaches the download events recorded for each line.
sort (optional): -id (default, newest first), id, created_at, -created_at.
Example: get all paid orders from last month:
Example: find all orders for a specific customer:
Example response (shortened):
Understanding key order fields
dl_access is either enabled or disabled. When disabled, the customer cannot access their download page. You can toggle this via the API.
is_imported is true when the order was imported from another system rather than created through Shopify checkout.
lines is the array of line items. Each line represents one digital product in the order. It includes the quantity, price in cents, the associated digital product, any assigned license keys, and optionally the download events if you used include=downloads.
price_cents is the price in the smallest currency unit (cents for USD/EUR, pence for GBP). Divide by 100 to get the display price.
Get a single order
GET /public-api/v1/orders/{id}
Returns the full details of one order, including lines, license keys, and optionally download events.
Enable or disable download access
POST /public-api/v1/orders/{id}/access
Toggles whether the customer can access their download page for this order. Useful for revoking access after a refund or re-enabling it after resolving a dispute.
Reset the download counter
POST /public-api/v1/orders/{id}/reset-downloads
Resets the download count for a specific line item back to zero. Use this when a customer has reached their download limit and needs fresh access, for example after a file update or a support request.
Resend the delivery email
POST /public-api/v1/orders/{id}/resend-email
Resends the download email to the customer. Optionally pass a new email address to update the customer's email on the order before sending.
Example: resend to the original email:
Example: resend to a different email (updates the order):
Associate files to an order line (UNIQUE delivery)
PUT /public-api/v1/orders/{id}/lines/{lineId}/files
Sets which files are delivered for a specific order line. This only applies to products with delivering_type: "UNIQUE", where each customer gets different files.
Pass an array of file IDs (from the Files endpoints) and optionally trigger the delivery email:
Setting send_email to true sends the delivery email to the customer after associating the files. Pass an empty file_ids array to remove all file associations from the line.
License keys
License key management is the most powerful part of the API. You can build a complete external license validation and distribution system without any third-party service.
List license keys
GET /public-api/v1/license-keys
Returns all license keys in your inventory.
Query parameters:
limit (optional, 1-100): results per page.
cursor (optional): pagination cursor.
status (optional): available (not yet assigned) or assigned (consumed by an order).
tag (optional): filter by tag.
q (optional, max 120 characters): search by key value.
sort (optional): -id (default), id, created_at, -created_at.
Example: list all available keys tagged "photoshop-plugin":
Example response (shortened):
Validate a license key
GET /public-api/v1/license-keys/validate?key=YOUR_KEY
Checks whether a key exists and whether it is assigned to an order. This is the endpoint your software calls when a customer activates their license.
Example:
Response:
valid is true when the key exists in your inventory. assigned is true when the key is linked to an order. If both are true, the customer has a legitimate license.
A key that is valid: true but assigned: false means it exists but has not been purchased yet. A key that is valid: false does not exist in your inventory.
Create license keys in batch
POST /public-api/v1/license-keys
Batch-create up to 5,000 license keys in a single request. You can tag them for organization and control how duplicates are handled.
Body:
keys (required, array of strings, 1-5,000): the key strings to add.
tag (optional, max 120 characters): a label to group the keys, for example the product name or batch identifier.
duplicates (optional): skip (default, ignore existing keys), create (insert duplicates anyway), fail (reject the entire batch if any key already exists).
Example: import 3 keys from your generator:
Supports an optional Idempotency-Key header. If you send the same idempotency key within a time window, the API returns the same response without creating duplicates. Use this to safely retry failed requests.
Assign a key to an order
POST /public-api/v1/license-keys/{id}/assign
Links an available key to a specific order by order name. Optionally sends the delivery email to the customer.
The key must be in available status. If it is already assigned, the request fails.
Unassign a key from an order
POST /public-api/v1/license-keys/{id}/unassign
Releases a key from its order, making it available again in inventory. Use this when processing a refund or when a key was assigned by mistake.
Delete a license key
DELETE /public-api/v1/license-keys/{id}
Permanently removes an unassigned key from inventory. The key must be unassigned first. If the key is currently assigned to an order, unassign it before deleting.
Files
List files
GET /public-api/v1/files
Returns all files in your library.
Query parameters:
limit (optional, 1-100): results per page.
cursor (optional): pagination cursor.
q (optional, max 120 characters): search by file name.
type (optional): filter by exact MIME type, for example application/pdf or application/zip.
uploaded (optional, true or false): filter by upload completion status.
include (optional): pass products to see which digital products each file is linked to.
sort (optional): -id (default), id, created_at, -created_at.
Example: list all PDF files:
Example response (shortened):
Upload a file
POST /public-api/v1/files
Uploads a file to your library. Send the file as multipart/form-data.
Limits: Maximum 25 MB per file. Rate limited to 6 uploads per minute.
Example:
Keep your API token server-side. For front-end uploads, proxy the request through your own backend. Never expose your token in client-side JavaScript.
Delete a file
DELETE /public-api/v1/files/{id}
Removes a file from storage and the catalog. The API refuses the request with 409 Conflict if the file is still attached to a digital product, an order line, or a download link. Detach the file first, then delete.
Download links
Create a secure download link
POST /public-api/v1/download-links
Bundles one or more files into a shareable download URL. Optionally set a download limit and enable PDF stamping (watermarking).
Body:
file_ids (required, array, 1-100): the file IDs to include.
use_download_limit (optional, boolean): enable a download limit on this link.
download_limit (optional, integer): max number of downloads. Only applies when use_download_limit is true. 0 means unlimited.
use_stamping (optional, boolean): enable PDF watermarking on all PDFs in this link.
stamping_text (optional, max 500 characters): the text to watermark. For example the customer's name, email, or order number.
Example: create a watermarked download link limited to 3 downloads:
Download links can be created but not listed, edited, or deleted after creation. Store the returned URL when you create it.
Download statistics
Aggregated download stats
GET /public-api/v1/downloads/stats
Returns download counts and bandwidth for a time window. Defaults to the last 30 days if no dates are specified.
Query parameters:
start (optional, ISO 8601): window start.
end (optional, ISO 8601): window end.
Example: stats for May 2026:
Example response:
total_downloads is every download event recorded. counted_downloads excludes re-downloads. billable_downloads is what counts toward your plan usage. total_bandwidth_bytes is the raw bytes served.
Customer downloads
GET /public-api/v1/customers/{customer_gid}/downloads
Returns all digital orders and recorded download events for a specific customer. Use the Shopify customer GID (e.g. gid://shopify/Customer/987654321) or the numeric customer ID.
This is useful for building a customer-facing download history page or for support agents who need to see exactly what a customer downloaded and when.
Pagination
All list endpoints use cursor-based pagination. When the response includes "has_more": true, pass the next_cursor value as the cursor parameter in your next request:
The sort order is preserved across pages. Maximum page size is 100 results.
Error codes
200 Success.
201 Resource created successfully (files, license keys, download links).
400 Validation error. A required field is missing or in the wrong format.
401 Missing or invalid token.
403 Shop is inactive or access is restricted.
404 Resource not found. The ID does not exist.
409 Conflict. You are trying to delete a file that is still attached to a product, order, or download link.
413 File too large. The upload exceeds the 25 MB limit.
429 Rate limit exceeded. Space out your requests and retry after a moment.
Webhooks: real-time event notifications
While the API lets you pull data on demand, webhooks push data to you instantly. Every time an order is purchased, a delivery email is sent, or a customer downloads a file, Big Digital Downloads sends a signed HTTP POST to the URL you configure.
Webhooks are essential for building real-time integrations: CRM syncs, Slack notifications, analytics pipelines, fraud detection, or any workflow that needs to react to events as they happen without polling.
Set up a webhook endpoint
In your Shopify admin, open the Big Digital Downloads app.
Go to Settings > Webhooks.
Click Add endpoint.
Enter a name for your endpoint, for example "Zapier sync", "Analytics", or "CRM pipeline".
Paste your HTTPS URL. The URL must use HTTPS.
Check the events you want to receive.
Click Create.

Big Digital Downloads displays a signing secret starting with whsec_. Copy it immediately and store it securely. This secret is shown only once and you need it to verify incoming webhook requests on your server.
You can edit any endpoint later to change the URL or enable or disable specific events. Use the Test button to send a test event and the See deliveries button to check delivery history.
The 4 webhook events
digital_order.purchased fires when a customer completes a purchase that includes a digital product. The payload contains the full order with customer data, line items, prices, and financial status.
digital_order.delivered fires when the delivery email is sent for an order. This happens automatically after purchase for REGULAR and SCHEDULED delivery products, or when you manually send or resend the email. Use this to confirm that the customer actually received their download link.
file.downloaded fires the first time a customer downloads a specific file from their order. Use this for analytics, to trigger onboarding emails, or to log access events in your system.
file.redownloaded fires when a customer downloads a file they already downloaded before. Use this to detect unusual download patterns or to track engagement with your content.
Verify the webhook signature
Every webhook request is signed so you can confirm it really came from Big Digital Downloads and was not tampered with. The verification process uses the same pattern as Cowlendar webhooks: HMAC-SHA256 with the signing secret, computed over timestamp + "." + raw_body.
Check the request headers:
X-Webhook-Signature contains the HMAC signature.
X-Webhook-Timestamp contains the Unix timestamp.
Always compute the signature over the RAW request body, the exact bytes the server sent, not a parsed and re-serialized JSON object. Parsing and re-serializing can change whitespace or key order, which breaks the signature.
Reject requests with a timestamp older than 5 minutes to prevent replay attacks.
Node.js (Express):
Python (Flask):
PHP:
Test your webhook before going live
Each webhook endpoint has a Test button in the admin. Clicking it sends a test event to your URL using the same signing and headers as real events. Use this to confirm that your server can receive events, that HTTPS and firewall settings are correct, and that your signature verification code works.
After clicking Test, check the See deliveries button to see the HTTP status code your endpoint returned.
Webhook best practices
Respond within 10 seconds. If your handler needs to do heavy work like calling another API or writing to a database, accept the webhook immediately with 200, then process it in a background job.
Deduplicate events. Store every event ID you process. If you receive the same ID again during a retry, skip it.
Use constant-time comparison for signatures. crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python, and hash_equals in PHP.
Current limitations
Orders are created through Shopify checkout, not the API. The API provides read access and post-purchase management (resend emails, toggle access, reset counters), but cannot create new orders.
Digital products can only be partially updated. You can change download limits and link expiry via API. All other product settings (name, files, delivery type, access mode) are managed from the admin.
License keys cannot be edited after creation. The key string itself is immutable. If you need to change a key value, delete the old one and create a new one.
Download links cannot be listed, edited, or deleted after creation. Store the URL when you create it.
File uploads are limited to 25 MB and 6 per minute. For larger files, upload them through the admin interface which supports bigger sizes.
Files cannot be downloaded through the API. The API manages your file library (list, upload, delete), but does not provide direct download URLs. Files are delivered to customers through order emails and download pages.
Rate limits apply. If you send too many requests in a short window, the API returns 429. For bulk operations like exporting all orders, add a short delay between paginated requests, for example 200 to 500 ms.
Webhook secrets are shown only once. If you lose your signing secret, delete the endpoint and create a new one to get a fresh secret.
Webhooks require HTTPS. HTTP endpoints are not accepted.
FAQ
Can I use the API with Zapier or Make without writing code?
Yes. For webhooks (receiving events from Big DD), create a "Custom Webhook" trigger in Zapier or Make, copy the URL they give you, and add it as an endpoint in Big DD Settings > Webhooks. For the API (sending requests to Big DD), use the "HTTP Request" action with your Bearer token to call any endpoint.
Can I build a license validation system with the API?
Yes. This is one of the strongest features. Your software calls GET /license-keys/validate?key=XXXXX on launch. The response tells you whether the key exists (valid) and whether it is assigned to an order (assigned). Both must be true for a legitimate license. No third-party license service needed.
What happens if my webhook endpoint goes down?
Big DD retries failed deliveries automatically. After multiple consecutive failures, the endpoint may be disabled. You can re-enable it from Settings > Webhooks once your server is back.
Can I have multiple webhook endpoints?
Yes. Create as many as you need, each with different event selections and URLs.
Last updated