E.4 Rate Limits, Financial Fields Format, Terms of Service
This section outlines the general rules and requirements for API usage, financial data formatting, and service terms that govern the SSO (OAuth) integration. Compliance with these rules is essential for reliable and secure operation.
Rate Limiting
Rate Limit Policy
Request Limits
- GET Requests: No rate limits for GET requests
- PUT/POST/DELETE Requests: Rate limits apply to all modifying requests
- Threshold: Requests per hour threshold enforced
- Exceeding Limits: New requests rejected when threshold exceeded
Rate Limit Implementation
// Rate limit response example
{
"error": "Too Many Requests",
"message": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"details": {
"limit": 1000,
"remaining": 0,
"resetTime": "2023-06-15T11:00:00Z",
"retryAfter": 3600
}
}
Rate Limit Headers
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1686828000
Retry-After: 3600
Best Practices for Rate Limiting
Request Optimization
- Batch Operations: Combine multiple operations into single requests
- Efficient Polling: Use appropriate polling intervals
- Caching: Cache responses to reduce redundant requests
- Conditional Requests: Use conditional requests when possible
Error Handling
// Rate limit handling
async function makeRequest(url, options = {}) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 60000;
console.log(`Rate limit exceeded. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
return makeRequest(url, options); // Retry request
}
return response;
} catch (error) {
console.error('Request failed:', error);
throw error;
}
}
Exponential Backoff
// Exponential backoff implementation
async function makeRequestWithBackoff(url, options = {}, maxRetries = 3) {
let retryCount = 0;
while (retryCount < maxRetries) {
try {
const response = await fetch(url, options);
if (response.status === 429) {
retryCount++;
const waitTime = Math.min(1000 * Math.pow(2, retryCount), 30000);
console.log(`Rate limit exceeded. Retry ${retryCount}/${maxRetries} in ${waitTime}ms`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
return response;
} catch (error) {
if (retryCount === maxRetries - 1) throw error;
retryCount++;
const waitTime = Math.min(1000 * Math.pow(2, retryCount), 30000);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
}
Financial Fields Format
Monetary Value Representation
Money Digits Multiplier
Financial fields use a multiplier system for precise decimal representation:
- Fields Affected:
balance,bonus,nonWithdrawableBonus,equity,usedMargin,freeMargin - Format: Values listed in 10^
moneyDigits - Calculation: Actual value = field value / (10^moneyDigits)
Example Calculation
// Example: Equity of 234512 with moneyDigits of 2
const fieldValues = {
equity: 234512,
moneyDigits: 2
};
const actualEquity = fieldValues.equity / Math.pow(10, fieldValues.moneyDigits);
// actualEquity = 234512 / 100 = 2345.12
Financial Data Structure
{
"account": {
"login": 123456,
"balance": 1000000,
"bonus": 50000,
"nonWithdrawableBonus": 25000,
"equity": 1050000,
"usedMargin": 100000,
"freeMargin": 950000,
"moneyDigits": 2,
"currency": "USD"
},
"calculatedValues": {
"balance": 10000.00,
"bonus": 500.00,
"nonWithdrawableBonus": 250.00,
"equity": 10500.00,
"usedMargin": 1000.00,
"freeMargin": 9500.00
}
}
Financial Field Validation
Client-Side Validation
// Financial field validation
function validateFinancialField(value, moneyDigits) {
const errors = [];
// Check if value is a number
if (typeof value !== 'number' || isNaN(value)) {
errors.push('Value must be a valid number');
return { isValid: false, errors };
}
// Check if value is non-negative
if (value < 0) {
errors.push('Value must be non-negative');
}
// Check precision
const maxValue = Number.MAX_SAFE_INTEGER;
if (value > maxValue) {
errors.push('Value exceeds maximum allowed amount');
}
// Calculate actual value for display
const actualValue = value / Math.pow(10, moneyDigits);
return {
isValid: errors.length === 0,
errors,
actualValue,
formattedValue: actualValue.toFixed(moneyDigits)
};
}
Server-Side Validation
// Server-side financial validation
function validateFinancialData(data) {
const requiredFields = ['balance', 'bonus', 'equity', 'usedMargin', 'freeMargin'];
const errors = [];
// Check required fields
requiredFields.forEach(field => {
if (!(field in data)) {
errors.push(`Missing required field: ${field}`);
}
});
// Validate moneyDigits
if (typeof data.moneyDigits !== 'number' || data.moneyDigits < 0 || data.moneyDigits > 8) {
errors.push('moneyDigits must be a number between 0 and 8');
}
// Validate financial fields
requiredFields.forEach(field => {
if (field in data) {
const validation = validateFinancialField(data[field], data.moneyDigits || 2);
if (!validation.isValid) {
errors.push(`${field}: ${validation.errors.join(', ')}`);
}
}
});
return {
isValid: errors.length === 0,
errors
};
}
Currency Handling
Supported Currencies
const supportedCurrencies = [
'USD', 'EUR', 'GBP', 'JPY', 'CHF', 'CAD', 'AUD', 'NZD',
'CNY', 'HKD', 'SGD', 'NOK', 'SEK', 'DKK', 'PLN', 'CZK',
'HUF', 'RON', 'BGN', 'HRK', 'RUB', 'TRY', 'ZAR', 'MXN'
];
function validateCurrency(currency) {
return supportedCurrencies.includes(currency);
}
Currency Formatting
// Currency formatting based on locale
function formatCurrency(amount, currency, locale = 'en-US') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(amount);
}
// Example usage
formatCurrency(1234.56, 'USD'); // "$1,234.56"
formatCurrency(1234.56, 'EUR', 'de-DE'); // "1.234,56 €"
Terms of Service
API Usage Terms
Acceptance of Terms
By using Spotware's API, brokers automatically agree to the company's terms of service. This includes:
- Usage Rights: Granted rights for API usage
- Compliance Requirements: Obligation to comply with all requirements
- Limitation of Liability: Limitations on Spotware liability
- Service Level: Service level agreements and expectations
Service Availability
- Best Effort: Services provided on best effort basis
- No Guarantee: No guarantee of uninterrupted service
- Maintenance: Scheduled maintenance may affect availability
- Emergency Maintenance: Emergency maintenance may be required
Data Usage and Privacy
Data Ownership
- Broker Data: Brokers retain ownership of their data
- User Data: User data protection and privacy requirements
- Analytics Data: Analytics data usage and sharing policies
- Compliance: Compliance with data protection regulations
Data Security
- Encryption: Data encryption requirements
- Access Control: Access control and authentication requirements
- Audit Trail: Audit trail maintenance requirements
- Breach Notification: Security breach notification requirements
Compliance and Legal Requirements
Regulatory Compliance
- Financial Regulations: Compliance with financial regulations
- Data Protection: GDPR and other data protection compliance
- AML/KYC: Anti-money laundering and know-your-customer requirements
- Reporting: Regulatory reporting requirements
Legal Obligations
- Jurisdiction: Applicable legal jurisdictions
- Dispute Resolution: Dispute resolution processes
- Governing Law: Governing law and legal framework
- Intellectual Property: Intellectual property rights and usage
Technical Requirements
Security Standards
- HTTPS Required: All API calls must use HTTPS
- Authentication: Proper authentication mechanisms required
- Authorization: Appropriate authorization controls required
- Data Protection: Data protection measures required
Performance Standards
- Response Times: Expected response time standards
- Availability: Service availability targets
- Scalability: Scalability requirements and expectations
- Monitoring: Monitoring and alerting requirements
Implementation Guidelines
Error Handling for Financial Data
Financial Error Responses
{
"error": "Financial Data Error",
"message": "Invalid financial data format",
"code": "INVALID_FINANCIAL_DATA",
"details": {
"field": "balance",
"value": "invalid_value",
"expectedFormat": "numeric value in 10^moneyDigits format",
"moneyDigits": 2
}
}
Financial Error Handling
function handleFinancialError(error) {
switch (error.code) {
case 'INVALID_FINANCIAL_DATA':
console.error('Financial data validation failed:', error.details);
// Display user-friendly error message
showUserError('Invalid financial data. Please check your input.');
break;
case 'INSUFFICIENT_FUNDS':
console.error('Insufficient funds for operation');
showUserError('Insufficient funds for this operation.');
break;
case 'CURRENCY_NOT_SUPPORTED':
console.error('Unsupported currency:', error.details.currency);
showUserError('Currency not supported. Please use a different currency.');
break;
default:
console.error('Unknown financial error:', error);
showUserError('An error occurred. Please try again.');
}
}
Rate Limiting Implementation
Client-Side Rate Limiting
class RateLimiter {
constructor(maxRequests, timeWindow) {
this.maxRequests = maxRequests;
this.timeWindow = timeWindow;
this.requests = [];
}
async makeRequest(requestFn) {
const now = Date.now();
// Remove old requests outside time window
this.requests = this.requests.filter(time => now - time < this.timeWindow);
// Check if rate limit exceeded
if (this.requests.length >= this.maxRequests) {
const oldestRequest = Math.min(...this.requests);
const waitTime = this.timeWindow - (now - oldestRequest);
console.log(`Rate limit reached. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
// Make request
this.requests.push(now);
return requestFn();
}
}
// Usage
const rateLimiter = new RateLimiter(100, 60000); // 100 requests per minute
async function apiCall(url, options) {
return rateLimiter.makeRequest(async () => {
const response = await fetch(url, options);
return response;
});
}
Financial Data Processing
Financial Calculations
class FinancialCalculator {
constructor(moneyDigits = 2) {
this.moneyDigits = moneyDigits;
this.multiplier = Math.pow(10, moneyDigits);
}
toFieldValue(actualValue) {
return Math.round(actualValue * this.multiplier);
}
toActualValue(fieldValue) {
return fieldValue / this.multiplier;
}
formatFieldValue(fieldValue) {
const actualValue = this.toActualValue(fieldValue);
return actualValue.toFixed(this.moneyDigits);
}
calculateFreeMargin(equity, usedMargin) {
const actualEquity = this.toActualValue(equity);
const actualUsedMargin = this.toActualValue(usedMargin);
const actualFreeMargin = actualEquity - actualUsedMargin;
return this.toFieldValue(actualFreeMargin);
}
calculateMarginLevel(equity, usedMargin) {
const actualEquity = this.toActualValue(equity);
const actualUsedMargin = this.toActualValue(usedMargin);
if (actualUsedMargin === 0) return 0;
return (actualEquity / actualUsedMargin) * 100;
}
}
// Usage
const calculator = new FinancialCalculator(2);
const balance = calculator.toFieldValue(10000.50); // 1000050
const actualBalance = calculator.toActualValue(balance); // 10000.50
const formattedBalance = calculator.formatFieldValue(balance); // "10000.50"
Monitoring and Compliance
API Usage Monitoring
- Request Tracking: Track all API requests and responses
- Rate Limit Monitoring: Monitor rate limit compliance
- Error Tracking: Track and analyze API errors
- Performance Monitoring: Monitor API performance metrics
Financial Data Monitoring
- Data Validation: Continuous validation of financial data
- Accuracy Checks: Regular accuracy checks and audits
- Compliance Monitoring: Monitor compliance with financial regulations
- Anomaly Detection: Detect and investigate anomalies
Compliance Monitoring
- Terms Compliance: Monitor compliance with terms of service
- Regulatory Compliance: Monitor regulatory compliance
- Security Compliance: Monitor security compliance
- Privacy Compliance: Monitor privacy compliance
Best Practices
Rate Limiting Best Practices
- Respect Limits: Always respect rate limit headers
- Implement Backoff: Use exponential backoff for retries
- Cache Responses: Cache responses to reduce requests
- Batch Operations: Use batch operations when possible
Financial Data Best Practices
- Precision: Maintain appropriate precision for financial calculations
- Validation: Always validate financial data
- Error Handling: Handle financial errors gracefully
- Audit Trail: Maintain complete audit trail for financial operations
Compliance Best Practices
- Regular Review: Regularly review compliance status
- Documentation: Maintain comprehensive documentation
- Training: Train staff on compliance requirements
- Monitoring: Continuous monitoring of compliance status
This comprehensive framework ensures proper API usage, accurate financial data handling, and compliance with all terms and regulatory requirements for SSO (OAuth) integration.