Skip to content

Quick Start with Synapse SDK

The Synapse SDK is your gateway to Filecoin Onchain Cloud, a decentralized, programmable cloud platform built on Filecoin. The SDK handles all the complexity of blockchain interactions, provider selection, and data management, so you can focus on building your application.

By the end of this guide, you’ll understand how to:

  • Install and configure the Synapse SDK
  • Connect to Filecoin networks (mainnet and calibration)
  • Prepare and fund your storage balance
  • Upload and download data

The Synapse SDK works in Node.js and the browser. Install it with your preferred package manager:

Terminal window
npm install @filoz/synapse-sdk viem

viem is a peer dependency and must be installed separately.

The Synapse class provides a complete, easy-to-use interface for interacting with Filecoin storage services.

Get started with storage in just a few lines of code.

import {
class Synapse
Synapse
,
const mainnet: Chain
mainnet
} from "@filoz/synapse-sdk"
import {
function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount

@description Creates an Account from a private key.

@returnsA Private Key Account.

privateKeyToAccount
} from 'viem/accounts'
// 1) Initialize the Synapse SDK
const
const synapse: Synapse
synapse
=
class Synapse
Synapse
.
Synapse.create(options: SynapseOptions): Synapse
create
({
SynapseOptions.account: `0x${string}` | Account
account
:
function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount

@description Creates an Account from a private key.

@returnsA Private Key Account.

privateKeyToAccount
('0x...'),
SynapseOptions.source: string | null
source
: 'my-app',
SynapseOptions.chain?: Chain | undefined
chain
:
const mainnet: Chain
mainnet
, // default is calibration testnet
// Uncomment for high-performance incentive-aligned data retrievability through Filecoin Beam
// withCDN: true
})
// 2) Prepare account (single tx handles deposit + approval)
const
const file: Uint8Array<ArrayBuffer>
file
= new
var TextEncoder: new () => TextEncoder

The TextEncoder interface takes a stream of code points as input and emits a stream of UTF-8 bytes.

MDN Reference

TextEncoder
().
TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>

The TextEncoder.encode() method takes a string as input, and returns a Global_Objects/Uint8Array containing the text given in parameters encoded with the specific method for that TextEncoder object.

MDN Reference

encode
(
`🚀 Welcome to decentralized storage on Filecoin Onchain Cloud!
Your data is safe here.
🌍 You need to make sure to meet the minimum size
requirement of 127 bytes per upload.`
);
const
const prep: PrepareResult
prep
= await
const synapse: Synapse
synapse
.
Synapse.storage: StorageManager
storage
.
StorageManager.prepare(options: PrepareOptions): Promise<PrepareResult>
prepare
({
PrepareOptions.dataSize: bigint
dataSize
:
var BigInt: BigIntConstructor
(value: bigint | boolean | number | string) => bigint
BigInt
(
const file: Uint8Array<ArrayBuffer>
file
.
Uint8Array<ArrayBuffer>.byteLength: number

The length in bytes of the array.

byteLength
),
})
if (
const prep: PrepareResult
prep
.
PrepareResult.transaction: {
depositAmount: bigint;
includesApproval: boolean;
execute: (options?: {
onHash?: (hash: Hash) => void;
}) => Promise<{
hash: Hash;
receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;
}>;
} | null
transaction
) {
const {
const hash: `0x${string}`
hash
} = await
const prep: PrepareResult
prep
.
PrepareResult.transaction: {
depositAmount: bigint;
includesApproval: boolean;
execute: (options?: {
onHash?: (hash: Hash) => void;
}) => Promise<{
hash: Hash;
receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;
}>;
}
transaction
.
execute: (options?: {
onHash?: (hash: Hash) => void;
}) => Promise<{
hash: Hash;
receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;
}>
execute
()
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`✅ Account funded and approved (tx: ${
const hash: `0x${string}`
hash
})`)
}
// 3) Upload — stores 2 copies across independent providers for durability
const {
const pieceCid: PieceLink
pieceCid
,
const size: number
size
,
const complete: boolean
complete
,
const copies: CopyResult[]
copies
,
const failedAttempts: FailedAttempt[]
failedAttempts
} = await
const synapse: Synapse
synapse
.
Synapse.storage: StorageManager
storage
.
StorageManager.upload(data: UploadPieceStreamingData, options?: StorageManagerUploadOptions): Promise<UploadResult>
upload
(
const file: Uint8Array<ArrayBuffer>
file
)
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`✅ Upload complete!`);
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`PieceCID: ${
const pieceCid: PieceLink
pieceCid
}`);
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`Size: ${
const size: number
size
} bytes`);
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`Stored on ${
const copies: CopyResult[]
copies
.
Array<CopyResult>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
} providers`);
if (!
const complete: boolean
complete
)
var console: Console
console
.
Console.warn(...data: any[]): void

The console.warn() static method outputs a warning message to the console at the 'warning' log level.

MDN Reference

warn
(`${
const failedAttempts: FailedAttempt[]
failedAttempts
.
Array<T>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
} copy attempt(s) failed`);
// 4) Download
const
const bytes: Uint8Array<ArrayBufferLike>
bytes
= await
const synapse: Synapse
synapse
.
Synapse.storage: StorageManager
storage
.
StorageManager.download(options: StorageManagerDownloadOptions): Promise<Uint8Array>
download
({
pieceCid: string | PieceLink
pieceCid
})
const
const decodedText: string
decodedText
= new
var TextDecoder: new (label?: string, options?: TextDecoderOptions) => TextDecoder

The TextDecoder interface represents a decoder for a specific text encoding, such as UTF-8, ISO-8859-2, KOI8-R, GBK, etc.

MDN Reference

TextDecoder
().
TextDecoder.decode(input?: AllowSharedBufferSource, options?: TextDecodeOptions): string

The TextDecoder.decode() method returns a string containing text decoded from the buffer passed as a parameter.

MDN Reference

decode
(
const bytes: Uint8Array<ArrayBufferLike>
bytes
);
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`✅ Download successful!`);
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`Downloaded data: ${
const decodedText: string
decodedText
}\n`);
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
("🎉 Data storage and retrieval successful!");

Now let’s break down each step…

  1. Initialize the SDK

    Set up the Synapse SDK with your credentials. In Node.js, you’ll typically use a private key:

    const
    const synapse: Synapse
    synapse
    =
    class Synapse
    Synapse
    .
    Synapse.create(options: SynapseOptions): Synapse
    create
    ({
    SynapseOptions.account: `0x${string}` | Account
    account
    :
    function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount

    @description Creates an Account from a private key.

    @returnsA Private Key Account.

    privateKeyToAccount
    ('0x...'),
    SynapseOptions.source: string | null
    source
    : 'my-app',
    SynapseOptions.chain?: Chain | undefined
    chain
    :
    const mainnet: Chain
    mainnet
    , // default is calibration testnet
    })

    In the browser, connect to the user’s wallet instead:

    import 'viem/window'
    import {
    function custom<provider extends EthereumProvider>(provider: provider, config?: CustomTransportConfig): CustomTransport

    @description Creates a custom transport given an EIP-1193 compliant request attribute.

    custom
    } from 'viem'
    const [
    const address: `0x${string}`
    address
    ] = await
    var window: Window & typeof globalThis

    The window property of a Window object points to the window object itself.

    MDN Reference

    window
    .
    Window.ethereum?: {
    on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    request: EIP1193RequestFn<EIP1474Methods>;
    } | undefined
    ethereum
    !.
    request: <undefined, {
    method: "eth_requestAccounts";
    }, `0x${string}`[]>(args: {
    method: "eth_requestAccounts";
    }, options?: EIP1193RequestOptions | undefined) => Promise<`0x${string}`[]>
    request
    ({
    method: "eth_requestAccounts"
    method
    : 'eth_requestAccounts' })
    const
    const synapse: Synapse
    synapse
    =
    class Synapse
    Synapse
    .
    Synapse.create(options: SynapseOptions): Synapse
    create
    ({
    SynapseOptions.account: `0x${string}` | Account
    account
    :
    const address: `0x${string}`
    address
    ,
    SynapseOptions.transport?: Transport | undefined
    transport
    :
    custom<{
    on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    request: EIP1193RequestFn<EIP1474Methods>;
    }>(provider: {
    on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    request: EIP1193RequestFn<EIP1474Methods>;
    }, config?: CustomTransportConfig): CustomTransport

    @description Creates a custom transport given an EIP-1193 compliant request attribute.

    custom
    (
    var window: Window & typeof globalThis

    The window property of a Window object points to the window object itself.

    MDN Reference

    window
    .
    Window.ethereum?: {
    on: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    removeListener: <event extends keyof EIP1193EventMap>(event: event, listener: EIP1193EventMap[event]) => void;
    request: EIP1193RequestFn<EIP1474Methods>;
    } | undefined
    ethereum
    !),
    SynapseOptions.source: string | null
    source
    : 'my-app',
    SynapseOptions.chain?: Chain | undefined
    chain
    :
    const mainnet: Chain
    mainnet
    , // default is calibration testnet
    })

    The source parameter identifies your application. It is stored as metadata on each dataset so that multiple apps sharing the same wallet can distinguish their own data.

  2. Payment Setup

    The prepare() method calculates the exact deposit needed for your data size and returns a single transaction that handles both funding and approval.

    To size your deposit, check the up-to-date rates in Pricing and use the storage costs guide for a detailed breakdown.

    // Check current USDFC balance
    const
    const walletBalance: bigint
    walletBalance
    = await
    const synapse: Synapse
    synapse
    .
    Synapse.payments: PaymentsService
    payments
    .
    PaymentsService.walletBalance(options?: {
    token?: TokenIdentifier;
    }): Promise<bigint>
    walletBalance
    ({
    token?: string | undefined
    token
    :
    const TOKENS: {
    readonly USDFC: "USDFC";
    readonly FIL: "FIL";
    }
    TOKENS
    .
    type USDFC: "USDFC"
    USDFC
    });
    const
    const formattedBalance: string
    formattedBalance
    =
    function formatUnits(value: bigint, options?: FormatUnitsOptions): string
    formatUnits
    (
    const walletBalance: bigint
    walletBalance
    );
    // Prepare account
    const
    const prep: PrepareResult
    prep
    = await
    const synapse: Synapse
    synapse
    .
    Synapse.storage: StorageManager
    storage
    .
    StorageManager.prepare(options: PrepareOptions): Promise<PrepareResult>
    prepare
    ({
    PrepareOptions.dataSize: bigint
    dataSize
    : 1073741824n, // 1 GiB
    });
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    ("Deposit needed:",
    const prep: PrepareResult
    prep
    .
    PrepareResult.costs: getUploadCosts.OutputType
    costs
    .
    depositNeeded: bigint
    depositNeeded
    );
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    ("Rate per month:",
    const prep: PrepareResult
    prep
    .
    PrepareResult.costs: getUploadCosts.OutputType
    costs
    .
    rate: {
    perEpoch: bigint;
    perMonth: bigint;
    }
    rate
    .
    perMonth: bigint
    perMonth
    );
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    ("Ready to upload:",
    const prep: PrepareResult
    prep
    .
    PrepareResult.costs: getUploadCosts.OutputType
    costs
    .
    ready: boolean
    ready
    );
    // Execute the transaction if needed (handles deposit + approval in one tx)
    if (
    const prep: PrepareResult
    prep
    .
    PrepareResult.transaction: {
    depositAmount: bigint;
    includesApproval: boolean;
    execute: (options?: {
    onHash?: (hash: Hash) => void;
    }) => Promise<{
    hash: Hash;
    receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;
    }>;
    } | null
    transaction
    ) {
    const {
    const hash: `0x${string}`
    hash
    } = await
    const prep: PrepareResult
    prep
    .
    PrepareResult.transaction: {
    depositAmount: bigint;
    includesApproval: boolean;
    execute: (options?: {
    onHash?: (hash: Hash) => void;
    }) => Promise<{
    hash: Hash;
    receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;
    }>;
    }
    transaction
    .
    execute: (options?: {
    onHash?: (hash: Hash) => void;
    }) => Promise<{
    hash: Hash;
    receipt: TransactionReceipt<bigint, number, "success" | "reverted", TransactionType> | null;
    }>
    execute
    ();
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    (`Account funded and approved (tx: ${
    const hash: `0x${string}`
    hash
    })`);
    }
  3. Store and Download Data

    Upload data to decentralized storage and retrieve it:

    // Upload data (stores 2 copies by default for durability)
    const
    const file: Uint8Array<ArrayBuffer>
    file
    = new
    var TextEncoder: new () => TextEncoder

    The TextEncoder interface takes a stream of code points as input and emits a stream of UTF-8 bytes.

    MDN Reference

    TextEncoder
    ().
    TextEncoder.encode(input?: string): Uint8Array<ArrayBuffer>

    The TextEncoder.encode() method takes a string as input, and returns a Global_Objects/Uint8Array containing the text given in parameters encoded with the specific method for that TextEncoder object.

    MDN Reference

    encode
    (
    `Welcome to decentralized storage on Filecoin Onchain Cloud!
    Your data is safe here.
    You need to make sure to meet the minimum size
    requirement of 127 bytes per upload.`
    );
    const {
    const pieceCid: PieceLink
    pieceCid
    ,
    const complete: boolean
    complete
    ,
    const copies: CopyResult[]
    copies
    ,
    const failedAttempts: FailedAttempt[]
    failedAttempts
    } = await
    const synapse: Synapse
    synapse
    .
    Synapse.storage: StorageManager
    storage
    .
    StorageManager.upload(data: UploadPieceStreamingData, options?: StorageManagerUploadOptions): Promise<UploadResult>
    upload
    (
    const file: Uint8Array<ArrayBuffer>
    file
    );
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    (`Stored on ${
    const copies: CopyResult[]
    copies
    .
    Array<CopyResult>.length: number

    Gets or sets the length of the array. This is a number one higher than the highest index in the array.

    length
    } providers`);
    if (!
    const complete: boolean
    complete
    )
    var console: Console
    console
    .
    Console.warn(...data: any[]): void

    The console.warn() static method outputs a warning message to the console at the 'warning' log level.

    MDN Reference

    warn
    (`${
    const failedAttempts: FailedAttempt[]
    failedAttempts
    .
    Array<T>.length: number

    Gets or sets the length of the array. This is a number one higher than the highest index in the array.

    length
    } copy attempt(s) failed`);
    // Download data from any provider that has it
    const
    const downloadedData: Uint8Array<ArrayBufferLike>
    downloadedData
    = await
    const synapse: Synapse
    synapse
    .
    Synapse.storage: StorageManager
    storage
    .
    StorageManager.download(options: StorageManagerDownloadOptions): Promise<Uint8Array>
    download
    ({
    pieceCid: string | PieceLink
    pieceCid
    });
    const
    const decodedText: string
    decodedText
    = new
    var TextDecoder: new (label?: string, options?: TextDecoderOptions) => TextDecoder

    The TextDecoder interface represents a decoder for a specific text encoding, such as UTF-8, ISO-8859-2, KOI8-R, GBK, etc.

    MDN Reference

    TextDecoder
    ().
    TextDecoder.decode(input?: AllowSharedBufferSource, options?: TextDecodeOptions): string

    The TextDecoder.decode() method returns a string containing text decoded from the buffer passed as a parameter.

    MDN Reference

    decode
    (
    const downloadedData: Uint8Array<ArrayBufferLike>
    downloadedData
    );
    var console: Console
    console
    .
    Console.log(...data: any[]): void

    The console.log() static method outputs a message to the console.

    MDN Reference

    log
    (`Downloaded data: ${
    const decodedText: string
    decodedText
    }`);

You’ve just stored and retrieved data on Filecoin. See the Developer Guides overview to find the right approach for your application, then dive into specific topics:

Want to understand the protocol? See Foundations & Architecture for how PDP, Filecoin Pay, and the service provider network fit together.

Join the #fil-builders on Filecoin Slack or Telegram for help and discussions.