Why WebSockets for Payments?
Polling /api/v1/payments/{id} every 3 seconds is wasteful and adds latency. Paychainly's Socket.io gateway pushes status updates the moment a deposit is detected — typically within 5 seconds of the on-chain confirmation.
Connecting from a React App
import { io } from 'socket.io-client';
import { useEffect, useState } from 'react';
function usePaymentStatus(paymentLinkId) {
const [status, setStatus] = useState('pending');
useEffect(() => {
const socket = io('https://api.paychainly.com', {
auth: { token: localStorage.getItem('jwt') },
});
socket.emit('subscribePayment', { paymentLinkId });
socket.on('paymentConfirmed', (data) => {
if (data.paymentLinkId === paymentLinkId) {
setStatus('confirmed');
}
});
return () => socket.disconnect();
}, [paymentLinkId]);
return status;
}
Events Reference
| Event | Direction | Payload |
|---|---|---|
| subscribePayment | Client → Server | { paymentLinkId } |
| paymentPending | Server → Client | { paymentLinkId, amount } |
| paymentConfirmed | Server → Client | { paymentLinkId, txHash, amount } |
| paymentExpired | Server → Client | { paymentLinkId } |
JWT Authentication
The gateway requires a valid JWT in the auth.token field. The same JWT from POST /api/auth/login is used.
Fallback Strategy
Always implement a fallback: if the WebSocket disconnects, fall back to polling the REST endpoint every 10 seconds. This ensures payment confirmation even through proxy timeouts or mobile network switches.