@pipsend/sdk
v0.3.2
Published
SDK oficial de Pipsend compatible con NodeJS y TypeScript
Maintainers
Readme
@pipsend/sdk
Official Pipsend SDK for Node.js and TypeScript. Complete trading platform integration with WebSocket support.
🚀 Features
- ✅ 6 Complete API Modules: Accounts, Orders, Positions, Trades, Market Data, Trading Groups
- ✅ TypeScript Native with 100+ complete types
- ✅ WebSocket Support with auto-reconnect and heartbeat
- ✅ Advanced Filtering (dates, ranges, multi-value, search)
- ✅ Dynamic Statistics grouped by any field
- ✅ Pagination Support for all list endpoints
- ✅ Dual Package (ESM + CommonJS)
- ✅ 56 Unit Tests passing
- ✅ Compatible with Node.js ≥16
📦 Installation
npm install @pipsend/sdkyarn add @pipsend/sdkpnpm add @pipsend/sdk🔐 Authentication
The SDK uses JWT-based authentication with automatic token refresh.
import { createClient } from "@pipsend/sdk";
const client = createClient({
server: "http://localhost:8080",
login: "1000", // Your admin/API login
password: "YourPassword", // Your admin/API password
});
// The SDK automatically:
// ✅ Authenticates on first API call
// ✅ Stores access and refresh tokens in memory
// ✅ Refreshes tokens automatically when they expire
// ✅ Re-authenticates if refresh failsAuthentication happens automatically - you don't need to call any login method. Just create the client and start making API calls.
Manual Authentication Control (Advanced)
If you need manual control over authentication:
// Check authentication status
const isAuthenticated = client.isAuthenticated();
// Manually refresh token
await client.refreshToken();
// Logout (clears tokens)
await client.logout();
// Get current token info
const tokenInfo = client.getTokenInfo();
console.log("Token expires at:", tokenInfo?.expiresAt);🔧 Quick Start
import { createClient } from "@pipsend/sdk";
// Create authenticated client
const client = createClient({
server: "http://localhost:8080",
login: "1000",
password: "DemoMaster",
});
const login = 50001;
// List accounts with filters
const accounts = await client.accounts.list({
state: "active",
country: "Mexico",
min_balance: 1000,
});
// Open a trade
const trade = await client.trades.open({
login,
symbol: "EURUSD",
action: "buy",
type: "market",
volume: 1.0,
stop_loss: 1.085,
take_profit: 1.095,
});
// Get market data
const candles = await client.marketData.getCandles({
symbol: "BTCUSD",
timeframe: "1h",
limit: 100,
});
// WebSocket real-time updates
client.stream.onPriceUpdate((price) => {
console.log("Price update:", price);
});
await client.stream.connect();📚 API Modules
1. Accounts API
Manage accounts with advanced filtering and statistics.
// Create a new trading account
const newAccount = await client.accounts.create({
trading_group: "Premium",
country: "MX",
master_password: "SecurePass123!",
investor_password: "InvestorPass123!",
email: "[email protected]",
first_name: "John",
last_name: "Doe",
leverage: 100,
state: "active",
});
// List accounts with filters
const accounts = await client.accounts.list({
state: "active",
country: "Mexico,United States",
trading_group: "Premium",
min_balance: 1000,
max_balance: 50000,
page: 1,
per_page: 20,
});
// Get statistics with filters
const stats = await client.accounts.getStatistics({
country: "Mexico",
state: "active",
});
// Get all account logins
const logins = await client.accounts.getLogins();
// Get account status/metrics (balance, equity, credit, margin)
const status = await client.accounts.getStatus(50001);
console.log("Balance:", status.data.balance);
console.log("Equity:", status.data.equity);
console.log("Credit:", status.data.credit);
console.log("Margin:", status.data.margin);
// Change passwords (master and/or investor)
await client.accounts.changePassword(50001, {
master: "NewMasterPass123!",
investor: "NewInvestorPass123!",
});
// Archive/Unarchive
await client.accounts.archive(50001);
await client.accounts.unarchive(50001);
// Update account information (partial update)
await client.accounts.update(50001, {
email: "[email protected]",
leverage: 200,
city: "Los Angeles",
trading_group: "Premium",
});
// Adjust balance or credit
await client.accounts.balance(50001, {
type: "balance",
amount: 500.0,
comment: "Client deposit",
});
await client.accounts.balance(50001, {
type: "credit",
amount: 1000.0,
comment: "Credit line increase",
});
// Subtract balance
await client.accounts.balance(50001, {
type: "balance",
amount: -200.0,
comment: "Withdrawal request",
});2. Orders API
Manage pending orders with statistics and validation.
// List orders with advanced filters
const orders = await client.orders.list({
login: "50001",
symbol: "EURUSD,GBPUSD",
order_type: "limit",
status: "new,partial",
created_from: "2025-01-01T00:00:00Z",
created_to: "2025-01-31T23:59:59Z",
price_min: 1.08,
price_max: 1.1,
sort_by: "created_at",
sort_order: "desc",
});
// Get statistics grouped by symbol
const stats = await client.orders.getStats({
login: "50001",
group_by: "symbol",
});
// Get totals by order type
const totals = await client.orders.getTotals({
login: "50001",
group_by: "order_type",
});
// Update order
await client.orders.update(12345, {
login: 50001,
stop_loss: 1.08,
take_profit: 1.095,
});
// Delete order
await client.orders.delete(12345, { login: 50001 });
// Validate orders
const checkResult = await client.orders.check({
filters: {
logins: [50001],
statuses: ["new"],
},
});3. Positions API
Manage open positions with recalculation support.
// List positions with filters
const positions = await client.positions.list({
login: "50001",
symbol: "EURUSD",
state: "open",
profit_min: 100,
profit_max: 1000,
});
// Get statistics grouped by type
const stats = await client.positions.getStats({
login: "50001",
state: "open",
group_by: "type",
});
// Get totals by symbol
const totals = await client.positions.getTotals({
login: "50001",
group_by: "symbol",
});
// Update position
await client.positions.update(1, {
login: 50001,
stop_loss: 1.0875,
take_profit: 1.0975,
});
// Delete position
await client.positions.delete(1, { login: 50001 });
// Recalculate positions
const checkResult = await client.positions.check({
filters: {
logins: [50001],
states: ["open"],
},
});4. Trades API
Execute trading operations with margin checking.
// Check margin before trading
const marginCheck = await client.trades.checkMargin({
login: 50001,
symbol: "EURUSD",
action: "buy",
volume: 1.0,
});
if (marginCheck.can_execute) {
// Open trade
const trade = await client.trades.open({
login: 50001,
symbol: "EURUSD",
action: "buy",
type: "market",
volume: 1.0,
stop_loss: 1.085,
take_profit: 1.095,
comment: "API Trade",
});
// Modify trade
await client.trades.modify({
login: 50001,
position_id: trade.position_id,
stop_loss: 1.0875,
take_profit: 1.0975,
});
// Calculate potential profit
const profitCalc = await client.trades.calculateProfit({
login: 50001,
symbol: "EURUSD",
action: "buy",
volume: 1.0,
open_price: 1.09,
close_price: 1.095,
});
// Close trade (partial or full)
await client.trades.close({
login: 50001,
position_id: trade.position_id,
volume: 0.5, // Partial close
comment: "Taking profit",
});
}
// Force price (for historical data import)
const historicalTrade = await client.trades.open({
login: 50001,
symbol: "EURUSD",
action: "buy",
type: "market",
volume: 1.0,
price: 1.085,
force_price: true,
force_timestamp: "2025-01-15T10:30:00Z",
});5. Market Data API
Query historical market data (minimum 1 hour old).
// Get candles with filters
const candles = await client.marketData.getCandles({
symbol: "BTCUSD,ETHUSD",
timeframe: "1h",
from: "2025-01-01T00:00:00Z",
to: "2025-01-02T00:00:00Z",
min_volume: 1000,
max_volume: 50000,
sort: "volume",
order: "desc",
limit: 100,
});
// Get last 100 candles
const recentCandles = await client.marketData.getCandles({
symbol: "BTCUSD",
timeframe: "1m",
limit: 100,
order: "desc",
});
// Get symbols with filters
const symbols = await client.marketData.getSymbols({
group: "CRYPTO_MAJOR",
has_data: true,
search: "bitcoin",
});
// Get groups hierarchy
const groups = await client.marketData.getGroups({
root_only: true,
sort: "symbol_count",
order: "desc",
});Timeframes: 1m, 5m, 15m, 1h, 4h, 1d
Note: Data must be at least 1 hour old (no real-time data).
6. Trading Groups API
Manage trading groups and their statistics.
// List trading groups
const groups = await client.tradingGroups.list({
page: 1,
per_page: 20,
});
// Get statistics
const stats = await client.tradingGroups.getStatistics();7. WebSocket API
Real-time updates for positions and balance with manual channel subscription.
// Enable WebSocket in config
const client = createClient({
server: "http://localhost:8080",
login: "1000",
password: "DemoMaster",
websocket: {
enabled: true,
autoConnect: false,
},
});
// Connect to WebSocket
await client.stream.connect();
// Subscribe to channels
client.stream.subscribe([
"positions:new", // New positions opened
"positions:closed", // Positions closed (total and partial)
"positions:updated", // Position PnL updates (throttled to 1 per 2s)
"accounts:balance", // Balance updates
]);
// Listen to position opened events
client.stream.onPositionOpened((event) => {
const pos = event.position;
console.log(
"Position opened:",
pos.symbol,
pos.side === 1 ? "LONG" : "SHORT",
pos.qty,
);
});
// Listen to position closed events
client.stream.onPositionClosed((event) => {
const pos = event.position;
console.log("Position closed:", pos.symbol, "PnL:", pos.net_pnl);
});
// Listen to position updated events (throttled)
client.stream.onPositionUpdated((event) => {
const pos = event.position;
console.log("Position update:", pos.position_id, "PnL:", pos.unrealized_pnl);
});
// Listen to balance updates
client.stream.onBalanceUpdated((event) => {
console.log("Balance:", event.balance, "Equity:", event.equity);
});
// Unsubscribe from channels
client.stream.unsubscribe(["positions:updated"]);
// Disconnect
client.stream.disconnect();Available Channels:
positions:new- New position openedpositions:closed- Position closed (total or partial)positions:updated- PnL updates (throttled to max 1 per 2 seconds)accounts:balance- Balance changes
Features:
- Manual subscription to specific channels
- Auto-reconnect with exponential backoff
- Heartbeat/ping-pong mechanism
- Automatic subscription restoration on reconnect
- Throttled position updates to reduce load
See WebSocket API Documentation for complete guide.
� Documentation
- Positions & Trading Guide - Complete guide for opening, closing, and modifying positions (SL/TP)
- WebSocket API - Real-time updates and streaming data
- Authentication - Authentication system and token management
�🔧 Configuration
Basic Configuration
const client = createClient({
server: "http://localhost:8080", // Required: API server URL
login: "1000", // Required: Admin/API login
password: "YourPassword", // Required: Admin/API password
});Advanced Configuration
const client = createClient({
server: "http://localhost:8080",
login: "1000",
password: "YourPassword",
// WebSocket configuration (optional)
websocket: {
enabled: true, // Enable WebSocket support
autoConnect: false, // Auto-connect on client creation
autoReconnect: true, // Auto-reconnect on disconnect
maxReconnectAttempts: 5, // Max reconnection attempts
heartbeatInterval: 30000, // Heartbeat interval in ms
},
});Configuration Options
| Option | Type | Required | Default | Description |
| -------------------------------- | ------- | -------- | ------- | ---------------------------------- |
| server | string | ✅ Yes | - | Pipsend API server URL |
| login | string | ✅ Yes | - | Admin/API login for authentication |
| password | string | ✅ Yes | - | Admin/API password |
| websocket.enabled | boolean | No | false | Enable WebSocket support |
| websocket.autoConnect | boolean | No | false | Auto-connect on creation |
| websocket.autoReconnect | boolean | No | true | Auto-reconnect on disconnect |
| websocket.maxReconnectAttempts | number | No | 5 | Max reconnection attempts |
| websocket.heartbeatInterval | number | No | 30000 | Heartbeat interval (ms) |
📦 API Response Structure
All API endpoints return a consistent response structure:
Success Response (without pagination)
{
status: "success",
status_code: "SUCCESS",
data: [...] // Array of results or single object
}Success Response (with pagination)
{
status: "success",
status_code: "SUCCESS",
data: [...],
meta: {
total: 156,
page: 1,
per_page: 20,
total_pages: 8,
has_next: true,
has_prev: false
}
}Error Response
{
status: "error",
status_code: "VALIDATION_ERROR",
message: "The provided data is not valid.",
errors?: [
{
field: "symbol",
message: "At least one symbol is required."
}
]
}Common Status Codes
Success:
SUCCESS- Operation successfulCREATED- Resource created successfully
Errors:
VALIDATION_ERROR(400) - Invalid parametersBAD_REQUEST(400) - Invalid requestUNAUTHORIZED(401) - Authentication requiredFORBIDDEN(403) - Insufficient permissionsNOT_FOUND(404) - Resource not foundCONFLICT(409) - Resource conflict (duplicate)INTERNAL_ERROR(500) - Server error
Market Data Specific:
SYMBOL_NOT_FOUND(404) - Symbol not foundINVALID_TIMEFRAME(400) - Invalid timeframeTIME_RANGE_TOO_LARGE(400) - Time range exceeds maximumDATA_TOO_RECENT(400) - Data must be at least 1 hour old
🎯 Common Patterns
Pagination
Option 1: Get all results (no pagination)
// Returns all results in a single array
const accounts = await client.accounts.list({
state: "active",
});
// Response: { status, status_code, data: [...] }Option 2: Paginated results
// Returns paginated results with metadata
const accounts = await client.accounts.list({
state: "active",
page: 1,
per_page: 20,
});
// Response: { status, status_code, data: [...], meta: {...} }
// Iterate through pages
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await client.accounts.list({
state: "active",
page,
per_page: 50,
});
// Process response.data
console.log(`Page ${page}:`, response.data.length);
hasMore = response.meta.has_next;
page++;
}Option 3: Limit results (ignores pagination)
// Get specific number of results
const candles = await client.marketData.getCandles({
symbol: "BTCUSD",
timeframe: "1h",
limit: 100, // Max: 10,000 for candles
});Multi-value Filters
Many filters accept comma-separated values:
// Multiple symbols (OR logic)
const positions = await client.positions.list({
symbol: "EURUSD,GBPUSD,USDJPY", // Positions in ANY of these symbols
});
// Multiple countries
const accounts = await client.accounts.list({
country: "Mexico,United States,Canada",
});
// Multiple states
const orders = await client.orders.list({
status: "new,partial", // Orders with status new OR partial
});Date Filters
All date parameters must be in ISO 8601 / RFC3339 format (UTC):
// Correct format
const positions = await client.positions.list({
opened_from: "2025-01-01T00:00:00Z",
opened_to: "2025-01-31T23:59:59Z",
});
// Also valid
const candles = await client.marketData.getCandles({
symbol: "BTCUSD",
timeframe: "1h",
from: "2025-01-15T10:30:00Z",
to: "2025-01-15T18:30:00Z",
});Note: Market data has a minimum age of 1 hour. The to parameter cannot be more recent than now - 1 hour.
Range Filters
Use min_* and max_* for numeric ranges:
// Balance range
const accounts = await client.accounts.list({
min_balance: 1000,
max_balance: 50000,
});
// Profit range
const positions = await client.positions.list({
profit_min: 100,
profit_max: 1000,
});
// Volume range
const candles = await client.marketData.getCandles({
symbol: "BTCUSD",
timeframe: "1h",
min_volume: 1000,
max_volume: 50000,
});Sorting
Most list endpoints support sorting:
const orders = await client.orders.list({
login: "50001",
sort_by: "created_at", // Field to sort by
sort_order: "desc", // 'asc' or 'desc'
});
const candles = await client.marketData.getCandles({
symbol: "BTCUSD",
timeframe: "1h",
sort: "volume", // Some endpoints use 'sort'
order: "desc", // instead of 'sort_by'/'sort_order'
});⚠️ Error Handling
All errors thrown by the SDK are instances of PipsendError with detailed information.
Basic Error Handling
import { PipsendError } from "@pipsend/sdk";
try {
const trade = await client.trades.open({
login: 50001,
symbol: "EURUSD",
action: "buy",
type: "market",
volume: 1.0,
});
console.log("Trade opened:", trade.position_id);
} catch (error) {
if (error instanceof PipsendError) {
console.error("Error code:", error.code);
console.error("Status code:", error.statusCode);
console.error("Message:", error.message);
// Check if it's a validation error
if (error.isValidationError()) {
console.error("Validation errors:", error.errors);
// Get formatted message with all details
console.error(error.getDetailedMessage());
}
}
}Handling Validation Errors (422)
When the API returns validation errors, the SDK provides detailed field-level information:
try {
const account = await client.accounts.create({
trading_group: "InvalidGroup",
country: "XYZ",
master_password: "short",
investor_password: "short",
email: "invalid-email",
first_name: "John",
last_name: "Doe",
});
} catch (error) {
if (error instanceof PipsendError && error.isValidationError()) {
console.log("Validation failed:");
// Access individual validation errors
error.errors?.forEach((err) => {
console.log(` - ${err.field}: ${err.message}`);
});
// Or get formatted message
console.log(error.getDetailedMessage());
// Output:
// The provided data is not valid.
// - trading_group: Trading group 'InvalidGroup' not found
// - country: Country 'XYZ' not found
// - master_password: The field master_password must be at least 8 characters.
// - email: The field email must be a valid email address.
}
}Error Properties
interface PipsendError {
message: string; // Error message
code: string; // Error code (e.g., 'VALIDATION_ERROR', 'NOT_FOUND')
statusCode: number; // HTTP status code (e.g., 422, 404, 500)
errors?: ValidationError[]; // Validation errors (for 422 responses)
response?: any; // Full error response from server
// Helper methods
isValidationError(): boolean; // Check if it's a validation error
getDetailedMessage(): string; // Get formatted message with details
}
interface ValidationError {
field: string; // Field name that failed validation
message: string; // Validation error message
}Common Error Scenarios
// 1. Insufficient margin
try {
await client.trades.open({...});
} catch (error: any) {
if (error.status_code === 'INSUFFICIENT_MARGIN') {
// Check margin first
const check = await client.trades.checkMargin({...});
console.log('Required margin:', check.margin_required);
}
}
// 2. Position not found
try {
await client.positions.update(999, {...});
} catch (error: any) {
if (error.status_code === 'NOT_FOUND') {
console.error('Position does not exist');
}
}
// 3. Invalid time range
try {
await client.marketData.getCandles({
symbol: 'BTCUSD',
timeframe: '1m',
from: '2025-01-01T00:00:00Z',
to: '2025-02-01T00:00:00Z' // Too large for 1m
});
} catch (error: any) {
if (error.status_code === 'TIME_RANGE_TOO_LARGE') {
console.error('Time range exceeds maximum for this timeframe');
// Max ranges: 1m=7d, 5m=30d, 15m=60d, 1h=6mo, 4h=1y, 1d=5y
}
}
// 4. Data too recent
try {
await client.marketData.getCandles({
symbol: 'BTCUSD',
timeframe: '1h',
to: new Date().toISOString() // Too recent!
});
} catch (error: any) {
if (error.status_code === 'DATA_TOO_RECENT') {
console.error('Market data must be at least 1 hour old');
}
}📝 TypeScript Support
The SDK is written in TypeScript and provides complete type definitions:
import type {
Account,
Order,
Position,
Candle,
Symbol,
OpenTradeRequest,
OpenTradeResponse,
} from "@pipsend/sdk";🧪 Testing
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Type checking
npm run typecheck
# Linting
npm run lint🛠️ Development
# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run dev📖 Examples
Check the examples/ directory for complete usage examples:
examples/api-usage.ts- Comprehensive API usageexamples/quick-start.ts- Quick start guide
🔗 Links
📄 License
MIT © 2025 Pipsend
🤝 Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
⚠️ Project Status
Current Version: 0.1.0 (Beta)
This SDK is in active development. The API may change between minor versions until version 1.0.0.
🌟 Features Roadmap
- [ ] Authentication with JWT tokens
- [ ] Rate limiting handling
- [ ] Retry logic with exponential backoff
- [ ] Request/response interceptors
- [ ] Batch operations
- [ ] Streaming data export
- [ ] Advanced error handling
- [ ] Performance metrics
- [ ] Request caching
- [ ] GraphQL support (future)
📊 Stats
- 6 API Modules: Accounts, Orders, Positions, Trades, Market Data, Trading Groups
- 100+ TypeScript Types: Fully typed interfaces
- 56 Unit Tests: Comprehensive test coverage
- Bundle Size: ~26 KB (minified)
- Zero Dependencies: Lightweight and fast
