html.surf
Sign in
Docs /Custom API Integration Dashboard →

Custom API Integration

Build custom integrations with any platform using Continuata's REST API for complete control over digital product delivery.

Common Integration Patterns

Order Processing

Generate download tokens when payments are confirmed.

  • Payment webhook → API call
  • Automatic token generation
  • Email delivery integration

Customer Portal

Build download libraries for returning customers.

  • Purchase history API
  • Download link generation
  • Usage analytics display

Basic Workflow

Here's a typical integration workflow for generating download tokens after a purchase:

1

Customer Completes Purchase

Your payment processor (Stripe, PayPal, etc.) confirms the transaction.

2

Generate Download Token

Call Continuata API to create a secure download token for the purchased products.

3

Deliver to Customer

Send the download link via email, add to customer account, or integrate with your platform.

API Endpoints

Generate Download URL

POST /api/generate-download-url

{
  "productId": "epic-drums-v1",
  "version": "1.0.0"
}

Response:

{
  "success": true,
  "productId": "epic-drums-v1",
  "version": "1.0.0",
  "downloadToken": "8b5d…",
  "downloadUrl": "https://continuata.io/download?token=8b5d…",
  "expiresAt": "2026-04-02T00:00:00.000Z"
}

List Org Purchases

Returns every purchase recorded against your organisation. There is currently no customerEmail filter — filter client-side, or point the customer at continuata.io/my for self-service.

GET /api/purchases

Download Sessions Report (CSV)

GET /api/reports/downloads?from=2026-04-01&to=2026-04-30

Admin-only. Returns CSV. See Downloads API for full parameters.

Example: Node.js Integration

Minimal example showing how to mint a download URL after a payment confirmation:

const express = require('express');
const app = express();
app.use(express.json());

const CONTINUATA_API_KEY = process.env.CONTINUATA_API_KEY;

async function mintDownloadUrl(productId, version) {
  const res = await fetch('https://continuata.io/api/generate-download-url', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${CONTINUATA_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ productId, version })
  });
  if (!res.ok) throw new Error(`Continuata API ${res.status}: ${await res.text()}`);
  return res.json();
}

app.post('/payment-success', async (req, res) => {
  const { customerEmail, items } = req.body;

  const downloadLinks = [];
  for (const item of items) {
    if (item.type !== 'digital') continue;
    const { downloadUrl, expiresAt } = await mintDownloadUrl(item.productId, item.version);
    downloadLinks.push({ product: item.name, downloadUrl, expiresAt });
  }

  // Send the per-item links *and* a link to https://continuata.io/my so
  // the customer can recover access after the 24-hour token expires.
  await sendDownloadEmail(customerEmail, downloadLinks);
  res.json({ success: true, downloadLinks });
});

app.listen(3000);

Error Handling

Errors return JSON with an error field and an HTTP status. Common cases:

async function safeMintDownloadUrl(productId, version) {
  const res = await fetch('https://continuata.io/api/generate-download-url', {
    method: 'POST',
    headers: { Authorization: `Bearer ${CONTINUATA_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ productId, version })
  });

  if (res.status === 401) throw new Error('Invalid API key — refresh in Settings → API Key');
  if (res.status === 403) throw new Error('Org role too low — generate the key under an admin account');
  if (res.status === 404) throw new Error(`No active manifest for ${productId}@${version}`);
  if (!res.ok) throw new Error(`Continuata API ${res.status}: ${await res.text()}`);

  return res.json();
}

Need Help? Check the Authentication docs for API setup, or contact support@continuata.com for integration assistance.