Asset Transfers
100Pay lets you transfer crypto assets in two ways:
- Internal transfers — move funds between wallets on the 100Pay network instantly using a user’s PayID or wallet address, with no network fees
- External (onchain) transfers — send crypto to any blockchain address on the respective network
Asset transfers require your Secret API Key and must be performed server-side only. Never expose your secret key in client-side or browser code.
Using the 100pay.js SDK
Install
npm
npm install @100pay-hq/100pay.jsInitialize the Client
import { Pay100 } from "@100pay-hq/100pay.js";
const client = new Pay100({
publicKey: "your_public_key",
secretKey: "your_secret_key", // Required for server-side operations
});Execute a Transfer
Use client.transfer.executeTransfer() to send assets to another wallet.
Internal Transfer
Send funds to another user on the 100Pay network via their PayID or internal wallet identifier. No blockchain fees apply.
const transfer = await client.transfer.executeTransfer({
amount: 50,
symbol: "USDT",
to: "user@payid", // Recipient's PayID or internal wallet identifier
transferType: "internal",
note: "Payment for invoice #42",
});
console.log(transfer.data.transactionId);
// => "txn_abc123..."External (Onchain) Transfer
Send funds to any blockchain wallet address. Set transferType to "external" and provide the on-chain wallet address in to.
const transfer = await client.transfer.executeTransfer({
amount: 0.01,
symbol: "ETH",
to: "0x1234567890abcdef1234567890abcdef12345678", // On-chain wallet address
transferType: "external",
note: "Payout to partner",
});
console.log(transfer.data.receipt);
// => Transaction receipt hashFor external transfers, the to field must be a valid on-chain address for the asset’s network. Make sure the recipient address matches the asset’s blockchain (e.g., an EVM address for ETH/USDT on Ethereum).
Using OAuth Access Token
If your integration uses 100Pay OAuth, pass the user’s access token to authorize transfers on their behalf:
const transfer = await client.transfer.executeTransfer({
amount: 25,
symbol: "USDT",
to: "partner@payid",
transferType: "internal",
oauthAccessToken: "user_oauth_access_token",
});Parameters
| Field | Type | Required | Description |
|---|---|---|---|
amount | number | string | âś… | Amount to transfer (must be greater than zero) |
symbol | string | âś… | Asset symbol/currency code (e.g. "USDT", "BTC", "ETH") |
to | string | ✅ | Destination — PayID for internal transfers, or blockchain address for external |
transferType | "internal" | "external" | — | Transfer mode. Defaults to "internal" if omitted |
note | string | — | Optional memo or note for the transfer record |
oauthAccessToken | string | — | OAuth 2.0 access token to authorize the transfer on behalf of a user |
Response
{
statusCode: 200,
message: "Transfer successful",
data: {
receipt: "0xabc...", // Transaction receipt / confirmation
transactionId: "txn_xyz...", // 100Pay internal transaction ID
timestamp: 1709500000000, // Unix timestamp
}
}| Field | Type | Description |
|---|---|---|
data.receipt | string | Transaction receipt or hash |
data.transactionId | string | Unique 100Pay transaction ID |
data.timestamp | string | number | When the transaction was processed |
Get Transfer History
Retrieve paginated transfer history for your account, with optional filters for currency, type, addresses, or account IDs.
const history = await client.transfer.getHistory({
page: 1,
limit: 20,
symbols: ["USDT", "BTC"], // Optional: filter by currency
type: "debit", // Optional: "credit" or "debit"
accountIds: ["acc_123"], // Optional: filter by account IDs
addresses: ["0x..."], // Optional: filter by wallet addresses
});
history.data.forEach((tx) => {
console.log(`${tx.type} ${tx.amount} ${tx.symbol} — ${tx.status}`);
});Parameters
| Field | Type | Required | Description |
|---|---|---|---|
page | number | — | Page number for pagination (default: 1) |
limit | number | — | Number of records per page (default: 10) |
symbols | string[] | — | Filter by one or more currency symbols |
type | string | — | Filter by transfer direction: "credit" or "debit" |
accountIds | string[] | — | Filter by specific account IDs |
addresses | string[] | — | Filter by wallet addresses |
Response
{
statusCode: 200,
message: "Transfer history retrieved",
data: [
{
_id: "txn_abc123",
symbol: "USDT",
from: "0xSenderAddress",
to: "0xRecipientAddress",
type: "debit",
amount: "50.00",
status: "completed",
note: "Payout to partner",
transactionHash: "0xhash...",
createdAt: "2024-03-01T12:00:00Z",
},
// ...
],
meta: {
total: 150,
page: 1,
limit: 20,
pages: 8,
hasNextPage: true,
hasPreviousPage: false,
}
}Transfer History Item
| Field | Type | Description |
|---|---|---|
_id | string | Unique transfer record ID |
symbol | string | Asset currency symbol |
from | string | Sender’s address or identifier |
to | string | Recipient’s address or identifier |
type | "credit" | "debit" | Transfer direction relative to your account |
amount | string | Transfer amount |
status | string | Transfer status (e.g. "completed", "pending", "failed") |
transactionHash | string | null | On-chain transaction hash (external transfers only) |
note | string | Optional memo attached to the transfer |
createdAt | Date | Timestamp when the transfer was created |
Pagination Metadata
| Field | Type | Description |
|---|---|---|
total | number | Total number of records |
page | number | Current page |
limit | number | Records per page |
pages | number | Total number of pages |
hasNextPage | boolean | Whether a next page exists |
hasPreviousPage | boolean | Whether a previous page exists |
Calculate Transfer Fees
Before executing a transfer, you can preview the fee breakdown for a given asset and transfer type.
// Fee for an external (onchain) USDT transfer
const fee = await client.transfer.calculateFee({
symbol: "USDT",
transferType: "external",
});
console.log(`Total fee: ${fee.data.totalFee} ${fee.data.feeSymbol}`);
console.log(`Network congestion: ${fee.data.networkCongestion}`);
// => Total fee: 1.5 USDT
// => Network congestion: low// Fee for an internal transfer (typically free or very low)
const internalFee = await client.transfer.calculateFee({
symbol: "USDT",
transferType: "internal",
});Parameters
| Field | Type | Required | Description |
|---|---|---|---|
symbol | string | âś… | Asset symbol to calculate fees for (e.g. "USDT", "ETH") |
transferType | "internal" | "external" | — | Transfer type. Use "external" for onchain fee estimates |
Response
{
statusCode: 200,
message: "Fee calculated",
data: {
baseFee: "0.5",
networkFee: "1.0",
totalFee: "1.5",
feeSymbol: "USDT",
networkCongestion: "low",
}
}| Field | Type | Description |
|---|---|---|
baseFee | string | number | 100Pay platform base fee |
networkFee | string | number | Blockchain network fee (external transfers only) |
totalFee | string | number | Total fee deducted from the transfer |
feeSymbol | string | Currency the fee is charged in |
networkCongestion | "low" | "medium" | "high" | Current network congestion level |
Internal transfers on the 100Pay network typically have lower fees than external onchain transfers. Always call calculateFee before presenting a transfer confirmation to your users.
TypeScript Types
interface ITransferAssetData {
amount: number | string;
symbol: string;
to: string;
transferType?: "internal" | "external";
note?: string;
oauthAccessToken?: string;
}
interface ITransferAssetResponse {
statusCode: number;
message: string;
data: {
receipt: string;
transactionId: string;
timestamp: string | number;
};
}
interface ITransferHistoryParams {
accountIds?: string[];
addresses?: string[];
symbols?: string[];
page?: number;
limit?: number;
type?: string; // "credit" | "debit"
}
interface ITransferHistoryResponse {
statusCode: number;
message: string;
data: ITransferHistoryItem[];
meta: {
total: number;
page: number;
limit: number;
pages: number;
hasNextPage: boolean;
hasPreviousPage: boolean;
};
}
interface ITransferHistoryItem {
_id: string;
accountId: string;
symbol: string;
from: string;
to: string;
type: "credit" | "debit";
amount: string;
status?: string;
transactionHash?: string | null;
note?: string;
createdAt?: Date;
updatedAt?: Date;
}
interface ITransferFeeParams {
symbol: string;
transferType?: "internal" | "external";
}
interface ITransferFeeResponse {
statusCode: number;
message: string;
data: {
baseFee: string | number;
networkFee?: string | number;
totalFee: string | number;
feeSymbol: string;
networkCongestion?: "low" | "medium" | "high";
};
}Next Steps
- Payments Overview — accept payments via Checkout, Payment Links, and Invoices
- Subaccounts — create dedicated crypto wallets for your customers
- Verify Payments — confirm transactions server-side after checkout