SDK Reference

A JavaScript/TypeScript SDK for licensing user-generated content. Streamlines digital asset licensing with smart license templates, automated agreement creation, and seamless royalty management.

Getting Started

To quickly get up and running with the Spaceport SDK, check out our Quick Start Guide.

Modules

Core

Class: SpaceportSDK

client.SpaceportSDK

Guides

API Authentication

API Authentication

The SDK supports API key authentication for backend services and server-side applications. When an API key is provided, it will be automatically included in all HTTP requests to v1 API endpoints.

Creating Assets and Listings

Creating Assets and Listings

Here’s a complete example of creating an asset and listing it for licensing:

import { SpaceportSDK, Network } from "@spaceport/sdk";
import { privateKeyToAccount } from "viem/accounts";
import { parseEther } from "viem";
import * as fs from "fs";
import * as path from "path";

async function createAssetAndListing() {
  // Initialize SDK with wallet
  const account = privateKeyToAccount(`0x${process.env.LICENSOR_PRIVATE_KEY}`);
  const sdk = SpaceportSDK.createWithAccount(account, {
    chain: "devnet",
    apiKey: process.env.SDK_API_KEY,
  });

  // 1. Get or create user
  let currentUser;
  try {
    currentUser = await sdk.users.getCurrentUser();
  } catch (error) {
    currentUser = await sdk.users.create({
      email: "[email protected]",
      firstName: "Alice",
      lastName: "Creator",
    });
  }

  // 2. Create asset record in Directus
  const logoPath = path.join(__dirname, "../media/spaceport_logo.png");
  const logoBuffer = fs.readFileSync(logoPath);
  const logoFile = new File([logoBuffer], "spaceport_logo.png", {
    type: "image/png",
  });

  const assetResult = await sdk.assets.create({
    name: "My Digital Asset",
    title: "My Digital Asset",
    userId: currentUser.id,
    organizationId: currentUser.organizationId,
    storageAccess: "public",
    description: "A unique digital creation",
    tags: ["art", "digital", "nft"],
    mediaFile: logoFile,
    thumbnailFile: logoFile,
  });

  // 3. Set up bond token approvals
  const requiredAllowance = parseEther("100"); // Adjust based on your needs
  await sdk.bondToken.approveAllForAmount(requiredAllowance);

  // 4. Get existing smart license
  const smartLicenses = await sdk.smartLicenses.getAll({ status: "published" });
  const smartLicenseHash = smartLicenses[0]?.smartLicenseHash;

  // 5. Create listing
  const listingResult = await sdk.listings.create({
    licensorAddress: account.address,
    price: parseEther("10"), // 10 tokens
    smartLicenseHash: smartLicenseHash,
    duration: BigInt(365 * 24 * 60 * 60), // 1 year
    licenseRoyalties: 200n, // 2%
    resellRoyalties: 500n, // 5%
    availableAgreements: 100,
    listingType: "AutoReview",
    assetIds: [assetResult.assetId],
    userId: currentUser.id,
    organizationId: currentUser.organizationId,
    title: "My Digital Asset License",
    description: "License for my unique digital creation",
    category: "digital-art",
  });

  // 6. Monitor job status
  if (listingResult.jobId) {
    const jobStatus = await sdk.utils.pollJobStatus(listingResult.jobId, {
      timeout: 300000, // 5 minutes
      interval: 3000, // 3 seconds
    });
    console.log("Listing creation status:", jobStatus.status);
  }
}

Job Monitoring

Job Monitoring

The SDK provides utilities for monitoring asynchronous job operations with configurable timeouts and intervals:

import { SpaceportSDK } from "@spaceport/sdk";

async function monitorJobs() {
  const sdk = SpaceportSDK.createWithAccount(account, {
    chain: "devnet",
    apiKey: process.env.SDK_API_KEY,
  });

  // Monitor a job with custom timeout and polling interval
  const jobStatus = await sdk.utils.pollJobStatus(jobId, {
    timeout: 300000, // 5 minutes timeout
    interval: 3000, // Poll every 3 seconds
  });

  // Handle different job statuses
  if (jobStatus.status === "completed") {
    console.log("Job completed successfully!");

    // Handle different data structures returned by jobs
    let results: any[] = [];
    if (Array.isArray(jobStatus.data)) {
      results = jobStatus.data;
    } else if (jobStatus.data?.value && Array.isArray(jobStatus.data.value)) {
      results = jobStatus.data.value;
    }

    console.log(`Processed ${results.length} items`);
  } else if (jobStatus.status === "failed") {
    console.error(`Job failed: ${jobStatus.error || "Unknown error"}`);
  }

  // Monitor multiple jobs in parallel
  const jobIds = ["job1", "job2", "job3"];
  const jobStatuses = await Promise.all(
    jobIds.map((id) => sdk.utils.pollJobStatus(id))
  );
}

Product Creation

Product Creation

The SDK provides product management functionality to create products from signed agreement assets:

import { SpaceportSDK } from "@spaceport/sdk";

async function productManagementExamples() {
  // Initialize SDK with a wallet and API key
  const sdk = SpaceportSDK.createWithAccount(account, {
    chain: "devnet",
    apiKey: process.env.SDK_API_KEY,
  });

  // Get current user
  const currentUser = await sdk.users.getCurrentUser();

  // Generate delegated attestation signatures for product creation
  const delegatedAttestationParams =
    await sdk.products.generateDelegatedAttestationSignatures(2); // For 2 products

  // Create products from agreement assets
  const productResult = await sdk.products.create({
    robloxAssetId: "123456789", // Roblox asset ID
    agreementId: "e5a654c3-a5c9-4651-9c93-d0e947154a1a", // Agreement ID from your database
    productDetails: [
      {
        assetId: "asset-uuid-1", // Asset ID from the agreement
        title: "My Awesome Product",
        description: "A product created from a signed agreement",
      },
      {
        assetId: "asset-uuid-2", // Another asset ID from the agreement
        title: "Another Great Product",
        description: "Second product from the same agreement",
      },
    ],
    delegatedAttestationParams, // Signatures generated above
  });

  console.log("Product creation result:", productResult);

  if (productResult.success) {
    console.log("🎉 Products created successfully!");
  }
}

Querying Data

Querying Data

The SDK provides a query module for accessing licensing information and agreement history. The query module automatically connects to the appropriate data source based on your network configuration:

import { SpaceportSDK, SpaceportChainType, QueryClient } from "@spaceport/sdk";

async function queryExamples() {
  // Option 1: Access the query module via the SDK instance
  // This automatically uses the environment from the SDK configuration
  const sdk = SpaceportSDK.create({ chain: "devnet" });
  console.log(`Using environment: ${sdk.query.getEnvironment()}`); // 'devnet'

  // Query active listings
  const activeListings = await sdk.query.listings.getActiveListings({
    first: 10,
  });
  console.log(`Found ${activeListings.totalCount} active listings`);

  // Option 2: Use the QueryClient directly with a specific environment
  // This is useful for standalone queries or when you need to query multiple environments
  const queryClient = new QueryClient("testnet");
  const testnetListings = await queryClient.listings.getActiveListings({
    first: 5,
  });

  // Common query examples

  // Get listings by licensor
  const licensorAddress = "0x1234...";
  const licensorListings = await sdk.query.listings.getListingsByLicensor(
    licensorAddress
  );

  // Get agreements for a licensee
  const licenseeAddress = "0xabcd...";
  const licenseeAgreements = await sdk.query.agreements.getAgreementsByLicensee(
    licenseeAddress
  );

  // Get agreements for a licensor
  const licensorAgreements = await sdk.query.agreements.getAgreementsByLicensor(
    licensorAddress
  );

  // Get a specific listing by ID
  const listingId = "0x1234..."; // Listing identifier
  const listing = await sdk.query.listings.getListingById(listingId);

  // Get active agreements
  const activeAgreements = await sdk.query.agreements.getBindingAgreements();

  // Get smart licenses
  const smartLicenses = await sdk.query.smartLicenses.getSmartLicenses({
    first: 5,
  });

  // Get a specific smart license by its hash
  const smartLicenseHash = "0xabcd...";
  const smartLicense = await sdk.query.smartLicenses.getSmartLicenseByHash(
    smartLicenseHash
  );

  // Execute custom queries using the underlying GraphQL client
  const client = sdk.query.getGraphQLClient();
  const customQuery = `
    query {
      listingObjects(where: { price_gt: "1000000000000000000" }) {
        id
        price
        licensor
        nftId
      }
    }
  `;
  const result = await client.query(customQuery).toPromise();
}

Royalty Management

Royalty Management

The SDK provides invoice generation functionality to create mock invoice data for testing and development:

import { SpaceportSDK } from "@spaceport/sdk";

async function generateInvoiceData() {
  const sdk = SpaceportSDK.createWithAccount(account, {
    chain: "devnet",
    apiKey: process.env.SDK_API_KEY,
  });

  // Generate mock invoice data for testing
  const assetPlatformId = `roblox-${Math.floor(Math.random() * 1000000000)}`;
  const csvResult = await sdk.invoices.generateMockInvoiceData({
    count: 8, // Number of invoices per quarter
    startYear: 2025, // Starting year for invoice data
    quarters: 4, // Number of quarters to generate
    assetPlatformId: assetPlatformId, // Platform-specific asset ID
  });

  // Create a File object from the CSV content
  const csvFile = new File([csvResult.csvContent], "mock-invoices.csv", {
    type: "text/csv",
  });

  console.log(
    `Generated ${csvResult.totalInvoices} invoices across ${csvResult.quarterRanges.length} quarters`
  );

  // Access quarter ranges for period-based operations
  csvResult.quarterRanges.forEach((quarter, index) => {
    console.log(
      `Q${
        index + 1
      }: ${quarter.start.toISOString()} - ${quarter.end.toISOString()}`
    );
  });

  return { csvFile, csvResult };
}

Signing License Agreements

Signing License Agreements

Here’s how to sign a license agreement:

import { SpaceportSDK } from "@spaceport/sdk";
import { privateKeyToAccount } from "viem/accounts";
import * as fs from "fs";
import * as path from "path";

async function signAgreement() {
  // Initialize SDK with licensee wallet
  const account = privateKeyToAccount(`0x${process.env.LICENSEE_PRIVATE_KEY}`);
  const sdk = SpaceportSDK.createWithAccount(account, {
    chain: "devnet",
    apiKey: process.env.SDK_API_KEY,
  });

  // 1. Get or create user
  let currentUser;
  try {
    currentUser = await sdk.users.getCurrentUser();
  } catch (error) {
    currentUser = await sdk.users.create({
      email: "[email protected]",
      firstName: "Bob",
      lastName: "Licensee",
    });
  }

  // 2. Get available listings
  const listings = await sdk.listings.getAll({ status: "published" });
  const firstListing = listings[0];

  // 3. Get smart license details
  const smartLicense = await sdk.smartLicenses.getByHash(
    firstListing.smart_license_hash,
    "published"
  );

  // 4. Prepare signing details
  const { requiredDetails, requiredFilesMetadata } =
    sdk.agreements.getRequiredSigningDetails(smartLicense);

  // Load required PDF file
  const pdfPath = path.join(__dirname, "../media/pdf-sample_0.pdf");
  const pdfBuffer = await fs.promises.readFile(pdfPath);
  const pdfFile = new File([pdfBuffer], "originalGameConcept.pdf", {
    type: "application/pdf",
  });

  // Fill in required details
  const licenseeSigningDetails = {
    details: {
      licenseeName: "Acme Corporation",
      licenseeOrgAddress: "123 Business St, Metropolis, NY 10001",
      licenseeAppointeeName: "Jane Smith",
      licenseeAppointeeEmail: "[email protected]",
      licenseeJurisdiction: "Delaware, USA",
      licenseeNotificationName: "Legal Department",
      licenseeNotificationEmail: "[email protected]",
      // Add other required fields...
    },
    files: {
      originalGameConcept: pdfFile,
    },
  };

  // 5. Create and sign agreement
  const result = await sdk.agreements.createAndSign({
    coreListingId: firstListing.id,
    onChainListingIds: firstListing.assets.map(
      (asset) => asset.on_chain_listing_id
    ),
    licenseeSigningDetails,
    storageAccess: "public",
  });

  // 6. Monitor job status
  if (result.jobId) {
    const jobStatus = await sdk.utils.pollJobStatus(result.jobId, {
      timeout: 300000,
      interval: 3000,
    });
    console.log("Agreement signing status:", jobStatus.status);
  }
}

User Management

User Management

The SDK provides user management functionality to create and retrieve users associated with wallet addresses:

import { SpaceportSDK } from "@spaceport/sdk";

async function userManagementExamples() {
  // Initialize SDK with a wallet
  const account = privateKeyToAccount(`0x${process.env.YOUR_PRIVATE_KEY}`);
  const sdk = SpaceportSDK.createWithAccount(account, {
    chain: "devnet",
    apiKey: process.env.SDK_API_KEY,
  });

  // Create a new user (wallet address is automatically included from SDK)
  const newUser = await sdk.users.create({
    email: "[email protected]",
    firstName: "John",
    lastName: "Doe",
  });
  console.log(`User created: ${newUser.userId}`);

  // Get the current user (based on the wallet address used to initialize the SDK)
  try {
    const currentUser = await sdk.users.getCurrentUser();
    console.log(
      `Current user: ${currentUser.email} (${currentUser.walletAddress})`
    );
  } catch (error) {
    console.log("No user found for current wallet address");
  }

  // Get a user by specific wallet address
  const walletAddress = "0x1234567890123456789012345678901234567890";
  try {
    const user = await sdk.users.getByWalletAddress(walletAddress);
    console.log(`User found: ${user.email}`);
    console.log(`Organization ID: ${user.organizationId}`);
    console.log(`Core login enabled: ${user.allowCoreLogin}`);
  } catch (error) {
    console.log(`No user found with wallet address: ${walletAddress}`);
  }
}

Query

Class: Query

query/client.QueryClient

Query Client for interacting with The Graph API This client provides methods for querying indexed blockchain data

Query/modules

Class: AgreementsQueryModule

query/modules/agreements.AgreementsQueryModule

Module for querying agreement data from The Graph

Class: ListingsQueryModule

query/modules/listings.ListingsQueryModule

Module for querying listing data from The Graph

Class: SmartLicensesQueryModule

query/modules/smartLicenses.SmartLicensesQueryModule

Module for querying smart license data from The Graph

Resources

Class: Agreement

resources/agreements.AgreementClient

The AgreementClient provides methods for interacting with licensing agreements on the Spaceport platform. Agreements represent the legally binding contract formed when a licensee accepts a licensor’s listing terms. This client handles actions like creating (signing), and accepting agreements, as well as querying agreement data.

Class: Asset

resources/assets.AssetClient

The AssetClient is used to manage digital assets within the Spaceport ecosystem. Assets are the core digital items, such as 3D models, audio files, or other creative works, that can be licensed and monetized. This client handles creating and managing the metadata and files associated with these assets.

Class: BondToken

resources/bondToken.BondTokenClient

The BondTokenClient provides an interface for interacting with the platform’s utility token, the Bond Token. This token is used for payments, staking, and other economic activities within the Spaceport and Cultura ecosystem. This client simplifies operations like checking balances, approving transfers, and minting new tokens.

Class: Invoice

resources/invoices.InvoiceClient

The InvoiceClient handles operations related to invoices, which are records of sales or usage of licensed assets. Invoices are typically imported from external platforms (e.g., Roblox sales data) and are used as the basis for calculating and distributing royalties to rights holders. This client can import, fetch, and even generate mock invoice data for testing.

Class: Listing

resources/listings.ListingClient

The ListingClient is used to manage listings on the Spaceport marketplace. A listing is an offer made by a licensor to license one or more assets under specific terms, such as price, duration, and royalties. This client handles creating and querying these listings.

Class: Product

resources/products.ProductClient

The ProductClient manages the lifecycle of products, which represent the instantiation of a licensed asset on an external platform (e.g., a specific t-shirt on Roblox created from a licensed design). Products link the Spaceport asset and agreement to its real-world counterpart, enabling tracking and royalty calculations.

Class: Royalty

resources/royalties.RoyaltyClient

The RoyaltyClient handles the complex process of royalty management. Royalties are the payments due to licensors based on the revenue generated by licensed products. This client provides methods to register sales data (via invoices), calculate royalties, and manage their payment and acceptance both on-chain and off-chain.

Class: SmartLicense

resources/smartLicenses.SmartLicenseClient

The SmartLicenseClient is used to manage Smart License templates on the blockchain. A Smart License is a reusable, on-chain template that defines the terms and conditions of a license, such as required licensee information or specific usage rights. These templates are then attached to listings to standardize and automate the licensing process.

Class: User

resources/users.UserClient

The UserClient manages user profiles within the Spaceport ecosystem. A user account is typically associated with a wallet address and holds information about the user’s identity and activities on the platform. This client handles user creation and retrieval.