Skip to content

Developer quick start

This is the shortest path from zero to a successful API call. For the full end-to-end (create, upload, deploy, mint) walk-through, see mint an NFT end-to-end.

Terminal window
bun add @highlightxyz/sdk

The SDK is an ESM-only TypeScript package. Works on Bun, Node 20+, and modern browsers.

A small set of endpoints work without auth. Use one to verify your setup:

import { createHighlightClient } from "@highlightxyz/sdk";
const client = createHighlightClient({
baseUrl: "https://api.highlightv2.xyz",
});
const chains = (await client.config.chains()).data!;
console.log(chains.map((c) => `${c.name} (${c.chainId})`));

If you see a list of chains, you’re wired up.

For anything write-related, you need a JWT. SIWE is the canonical path:

import { createSiweMessage } from "viem/siwe";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const { nonce } = (await client.user.siwe.nonce()).data!;
const message = createSiweMessage({
address: account.address,
chainId: 1,
domain: new URL("https://api.highlightv2.xyz").host,
nonce,
uri: "https://api.highlightv2.xyz",
version: "1",
issuedAt: new Date(),
expirationTime: new Date(Date.now() + 10 * 60 * 1000),
});
const signature = await account.signMessage({ message });
const { tokens } = (await client.user.signin({
body: { providerType: "Siwe", message, signature },
})).data!;
const authed = createHighlightClient({
baseUrl: "https://api.highlightv2.xyz",
auth: () => tokens.accessToken,
security: [{ type: "http", scheme: "bearer" }],
});

Access tokens last 15 minutes. See reference/auth for refresh patterns, Privy sign-in, and API keys.

const mine = (await authed.collection.list({
blockchains: [84532], // Base Sepolia
testnet: true,
types: ["OpenEdition", "LimitedEdition", "OneOfOne", "Series", "GenerativeSeries"],
limit: 20,
})).data!;
console.log(`${mine.pagination.total} collections`);

blockchains, testnet, and types are required — this is by design; unbounded listing is never what you want.

Every method returns { data, error, response }. No exceptions on non-2xx:

const res = await authed.collection.get({ highlightId: "does-not-exist" });
if (res.error) {
console.log(`${res.response?.status}: ${JSON.stringify(res.error)}`);
// e.g. "404: { name: \"CollectionNotFoundError\", ... }"
}

See reference/errors for the full typed-error catalog.