News WebSocket
News WebSocket Service¶
Overview¶
Bridge402's News WebSocket service provides real-time access to premium crypto news streams, bridged from Web2 sources to Web3 applications via x402 payments. This enables AI agents and decentralized applications to access professional-grade news feeds that were previously behind paywalls or subscription services.
The Bridge402 WebSocket API provides real-time access to crypto news streams. Access is controlled through x402 payments, ensuring only paying users can access the stream.
Pricing¶
- Base Rate: $0.0035 USDC per minute
- Token-Based Pricing (Solana): Hold Bridge402 tokens to unlock discounts
- 0 tokens: $15/day
- 5M+ tokens: $1/day
- Linear interpolation between tiers
- See Token-Based Pricing section below for details
Connection Process¶
1. Create Session¶
First, create a session using the /connect endpoint:
curl -X POST "https://bridge402.tech/connect" \
-H "X-PAYMENT: <base64-encoded-payment>" \
-d "duration_min=10"
Response:
{
"access_token": "eyJzZXNzaW9uX2lkIjoi...",
"expires_at": 1703123456.789,
"payment": {
"verified": true,
"settled": true,
"txHash": "0x1234...",
"network": "base"
}
}
2. Connect to WebSocket¶
Use the access token to connect to the WebSocket stream:
Message Types¶
Connection Confirmation¶
When you first connect, you'll receive a confirmation message:
News Messages¶
Real-time news messages can be either Twitter/X posts or news articles. The message format varies based on the source type.
Twitter/X Post Format¶
{
"title": "stacks.btc (@Stacks)",
"body": "we're excited to introduce a new companion that will automatically deposit more bitcoin in your wallet every 2 weeks just for holding bitcoin on stacks and enrolling in dual stacking https://t.co/t8r1ZkhsJa",
"icon": "https://pbs.twimg.com/profile_images/1764968185399267328/lrmnHOuN.jpg",
"image": "https://pbs.twimg.com/media/G4njjP3bAAACG16.jpg",
"urls": [],
"mentions": [],
"requireInteraction": true,
"type": "direct",
"link": "https://twitter.com/Stacks/status/1984367309054755272",
"info": {
"twitterId": "3285797414",
"isReply": false,
"isRetweet": false,
"isQuote": false,
"isSelfReply": false
},
"coin": "STX",
"actions": [
{
"action": "BINFUT_STXUSDT",
"title": "STXUSDT PERP",
"icon": "https://news.treeofalpha.com/static/images/binance_icon.png"
}
],
"suggestions": [...],
"time": 1761945009301,
"_id": "1984367309054755272",
"show_feed": true,
"show_notif": true
}
News Article Format¶
{
"title": "COINTELEGRAPH: MEXC apologizes to 'White Whale' trader over $3M freeze",
"source": "Blogs",
"url": "https://cointelegraph.com/news/mexc-white-whale-trader-token-freeze",
"time": 1761945308076,
"symbols": [],
"en": "COINTELEGRAPH: MEXC apologizes to 'White Whale' trader over $3M freeze",
"_id": "1761945308075CMatWWto3f",
"suggestions": [],
"delay": 5000
}
Common Fields:
| Field | Type | Description |
|---|---|---|
title |
string | Message/article title |
time |
number | Timestamp (milliseconds) |
_id |
string | Unique message identifier |
Twitter/X Post Fields:
| Field | Type | Description |
|---|---|---|
body |
string | Post content/body text |
icon |
string | Profile icon/image URL |
image |
string | Optional attached image URL |
link |
string | Link to original Twitter/X post |
coin |
string | Primary coin/token mentioned |
actions |
array | Available trading actions (exchanges, pairs) |
suggestions |
array | Coin suggestions with exchange symbols |
info |
object | Twitter metadata (isReply, isRetweet, etc.) |
News Article Fields:
| Field | Type | Description |
|---|---|---|
source |
string | News source name (e.g., "Blogs", "COINTELEGRAPH") |
url |
string | Link to original article |
en |
string | English title/description |
symbols |
array | Related trading symbols |
suggestions |
array | Coin suggestions |
delay |
number | Delay value (milliseconds) |
Session Management Messages¶
Renewal Prompt (Halfway Point)¶
When you're halfway through your session:
{
"type": "renewal_prompt",
"message": "You're halfway through your session. Extend now to avoid interruption (POST /extend with X-SESSION and X-PAYMENT).",
"expires_at": 1703123456,
"seconds_remaining": 150,
"docs": {
"extend_endpoint": "/extend",
"headers": ["X-SESSION: <your access_token>", "X-PAYMENT: <base64 x402>"]
}
}
Expiry Warning (30 seconds before)¶
{
"type": "expiry_soon",
"message": "Session expires in ~30 seconds. Extend via /extend to stay connected.",
"expires_at": 1703123456,
"seconds_remaining": 25
}
Session Extended¶
When session is successfully extended:
{
"type": "session_extended",
"message": "Session extended without disconnecting.",
"expires_at": 1703123456,
"seconds_remaining": 300
}
Session Extension¶
Automatic Extension¶
The WebSocket client should automatically extend sessions when:
- Halfway Point: When 50% of session time has elapsed
- Expiry Warning: When 30 seconds remain before expiry
Manual Extension¶
To manually extend a session:
curl -X POST "https://bridge402.tech/extend" \
-H "X-SESSION: <your-access-token>" \
-H "X-PAYMENT: <base64-encoded-payment>" \
-d "duration_min=5"
Error Handling¶
WebSocket Error Codes¶
- 4000: General error
- 4001: Invalid or expired token
Connection Issues¶
Handle these common scenarios:
- Token Expired: Reconnect with new session
- Network Disconnect: Implement reconnection logic
- Payment Required: Generate new payment and reconnect
Reconnection Strategy¶
class Bridge402Client {
constructor(apiUrl, privateKey) {
this.apiUrl = apiUrl;
this.privateKey = privateKey;
this.ws = null;
this.session = null;
this.reconnectAttempts = 0;
this.maxReconnectAttempts = 5;
}
async connect() {
try {
// Create session first
this.session = await this.createSession();
// Connect to WebSocket
this.ws = new WebSocket(`${this.apiUrl}/stream?token=${this.session.access_token}`);
this.ws.onopen = () => {
console.log('Connected to Bridge402 stream');
this.reconnectAttempts = 0;
};
this.ws.onmessage = (event) => {
this.handleMessage(JSON.parse(event.data));
};
this.ws.onclose = (event) => {
if (event.code === 4001) {
// Token expired, create new session
this.reconnect();
} else {
// Other error, attempt reconnection
this.reconnect();
}
};
} catch (error) {
console.error('Connection failed:', error);
this.reconnect();
}
}
async reconnect() {
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
console.error('Max reconnection attempts reached');
return;
}
this.reconnectAttempts++;
const delay = Math.pow(2, this.reconnectAttempts) * 1000; // Exponential backoff
console.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
setTimeout(() => {
this.connect();
}, delay);
}
handleMessage(message) {
if (message.type === 'renewal_prompt') {
this.extendSession();
} else if (message.type === 'expiry_soon') {
this.extendSession();
} else if (message.title) {
// News message
this.processNews(message);
}
}
async extendSession() {
try {
const payment = await this.createPayment(5); // Extend by 5 minutes
const response = await fetch(`${this.apiUrl}/extend`, {
method: 'POST',
headers: {
'X-SESSION': this.session.access_token,
'X-PAYMENT': payment,
'Content-Type': 'application/json'
},
body: JSON.stringify({ duration_min: 5 })
});
if (response.ok) {
const data = await response.json();
this.session.access_token = data.access_token;
this.session.expires_at = data.expires_at;
console.log('Session extended successfully');
}
} catch (error) {
console.error('Failed to extend session:', error);
}
}
}
Token-Based Pricing¶
Bridge402 offers tiered pricing for Solana users who hold Bridge402 tokens. This feature automatically applies discounts based on your token holdings.
How Token-Based Pricing Works¶
- Provide Wallet Address: Include your Solana wallet address as a query parameter when requesting an invoice
- Automatic Balance Query: The system queries your Bridge402 token balance on Solana
- Tiered Pricing: Your invoice is calculated based on your token holdings
- Transparent Pricing: The invoice response includes your token balance and calculated daily rate
Pricing Tiers¶
| Token Balance | Daily Rate | Per Minute |
|---|---|---|
| 0 tokens | $15.00 | $0.0104 |
| 1,000,000 | ~$12.20 | ~$0.0085 |
| 2,500,000 | $8.00 | $0.0056 |
| 5,000,000+ | $1.00 | $0.000694 |
Pricing uses linear interpolation between tiers. For example, if you hold 1.5M tokens, your rate would be approximately $10.20/day.
Token Details¶
- Token Mint:
86Qzt4Dpx51pYGj7TscfEEBbTspsnQJQpNQxodm6pump - Network: Solana Mainnet
- Automatic: No manual configuration needed
Usage Example¶
Request Invoice with Token-Based Pricing:
curl -X POST "https://bridge402.tech/connect?duration_min=60&network=sol&wallet_address=YOUR_SOLANA_WALLET_ADDRESS"
Response (with token balance):
{
"x402Version": 1,
"error": "X-PAYMENT header is required",
"accepts": [
{
"scheme": "exact",
"network": "solana",
"maxAmountRequired": "41667",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"payTo": "BjxbJg48jQmoBLJnRunB1CMY5SZwvcUmnXCaWNeSXBei",
"resource": "https://bridge402.tech/stream",
"description": "Access to Bridge402 crypto news stream for 60 minute(s) [Solana/USDC]",
"extra": {
"product": "Bridge402 News — 60 min (Solana)",
"minutes": 60,
"resourcePath": "/stream",
"feePayer": "2wKupLR9q6wXYppw8Gr2NvWxKBUqm4PPJKkQfoxHDBg4",
"tokenBalance": 2500000,
"pricePerDay": 8.0
}
}
]
}
Key Fields in Response:
- tokenBalance: Your current Bridge402 token balance
- pricePerDay: Your calculated daily rate based on token holdings
- maxAmountRequired: Invoice amount in atomic units (already discounted)
Integration Tips¶
- Always Provide Wallet Address: For Solana payments, always include
wallet_addressto get the best pricing - Check Invoice Response: The
extrafield contains your token balance and pricing information - Automatic Application: Discounts are automatically applied - no additional steps required
- Works with Extensions: Token-based pricing also applies to session extensions
Example Code¶
// Request invoice with wallet address for token-based pricing
const response = await fetch(
`https://bridge402.tech/connect?duration_min=60&network=sol&wallet_address=${walletAddress}`
);
const invoice = await response.json();
const solanaInvoice = invoice.accepts.find(acc => acc.network === 'solana');
if (solanaInvoice.extra.tokenBalance) {
console.log(`Token balance: ${solanaInvoice.extra.tokenBalance}`);
console.log(`Daily rate: $${solanaInvoice.extra.pricePerDay}`);
console.log(`Discount applied!`);
}
Best Practices¶
1. Session Management¶
- Always monitor session expiry
- Implement automatic extension logic
- Handle session renewal gracefully
2. Message Processing¶
- Process messages asynchronously
- Implement message queuing for high-volume scenarios
- Filter messages based on your needs
3. Error Handling¶
- Implement exponential backoff for reconnections
- Log errors for debugging
- Provide user feedback for connection issues
4. Performance¶
- Use connection pooling for multiple streams
- Implement message batching if needed
- Monitor memory usage for long-running connections
Rate Limits¶
- Connection Rate: 10 connections per minute per IP
- Message Rate: No limit on incoming messages
- Extension Rate: 1 extension per minute per session
Security Considerations¶
- Always use WSS (WebSocket Secure) in production
- Validate all incoming messages
- Implement proper authentication checks
- Monitor for suspicious activity
Troubleshooting¶
Common Issues¶
- Connection Refused: Check API URL and network connectivity
- Token Invalid: Verify session token format and expiry
- Payment Failed: Check x402 payment format and network
- Messages Not Received: Check WebSocket connection status
Debug Mode¶
Enable debug logging to troubleshoot issues:
// Enable WebSocket debug logging
WebSocket.debug = true;
// Or use browser dev tools
console.log('WebSocket state:', ws.readyState);
console.log('Session expiry:', new Date(session.expires_at * 1000));
Monitoring¶
Monitor these metrics:
- Connection uptime
- Message processing rate
- Session extension frequency
- Error rates and types