Debuta uses Socket.io for every feature that requires sub-second delivery: incoming messages, match notifications, presence updates, date suggestion pop-ups, and peer-to-peer call signalling. This page documents every event, its direction, and its payload, drawn directly fromDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/desarrolladorandres2026-gif/Native-tailwind/llms.txt
Use this file to discover all available pages before exploring further.
socket.js and the React Native client contexts.
The Socket.io server runs on the same Express HTTP server. There is no separate WebSocket URL.
Connection
Connect using the standard Socket.io client with JWT authentication passed in theauth object:
What happens on connect
JWT validation
The server middleware verifies the
token from socket.handshake.auth. An invalid or missing token causes an immediate connect_error with the message "Token inválido" or "Token requerido".Room assignment
The authenticated user’s socket is joined to a personal room named
user:<userId>. All server-initiated events targeting a specific user are emitted to this room.Presence broadcast
The server broadcasts
usuario:online with { userId } to all other connected clients.Presence events
These events track which users are currently online. Usepresencia:estado to check a specific user’s status before placing a call.
| Event | Direction | Payload | Description |
|---|---|---|---|
usuario:online | server → all | { userId: string } | Broadcast when a user connects |
usuario:offline | server → all | { userId: string, lastSeen: Date } | Broadcast when a user disconnects |
presencia:estado | client → server | { userId: string } | Request the online status of a specific user |
presencia:respuesta | server → requester | { userId: string, online: boolean, lastSeen: Date | null } | Response to a presencia:estado query |
Example — check if a user is online
Messaging events
| Event | Direction | Payload | Description |
|---|---|---|---|
mensaje:enviar | client → server | { paraId: string, content: string } | Send a text (or image URL) message to a matched user |
mensaje:nuevo | server → sender + recipient | Message object + senderName + senderPhoto | New message broadcast to both participants |
mensajes:leer | client → server | { deId: string } | Mark all messages received from deId as read |
cita:sugerencia | server → both match users | Date suggestion payload | Emitted automatically after the 5th message in a match |
cita:nueva-sugerencia | server → both match users | Date suggestion payload | Emitted when a new venue is proposed via POST /api/matches/:id/suggest-new-place |
cita:estado-actualizado | server → partner | { matchId, aceptoPor, recomendacion } | Emitted when one user accepts a date suggestion |
cita:confirmada | server → restaurant partner | { matchId, pareja[], restaurante, fechaSugerida } | Emitted to the restaurant’s associated account when both users accept |
mensaje:enviar payload
The
_id of the user you want to message. Both users must have a mutual match or the server responds with an error event.Message text content, or a Cloudinary URL for an image message. Whitespace is trimmed server-side.
mensaje:nuevo payload
cita:sugerencia payload
Example — send a message and listen for delivery
Call events
Debuta uses WebRTC for peer-to-peer audio and video calls, with Socket.io as the signalling channel. The call flow exchanges SDP offers/answers and ICE candidates through these events.| Event | Direction | Payload | Description |
|---|---|---|---|
call:request | client → server | { paraId, signalData, isVideo, callerName, callerPhoto } | Initiate a call; server validates mutual match before forwarding |
call:incoming | server → callee | { fromId, signalData, isVideo, callerName, callerPhoto } | Forwarded to the callee; signalData is the SDP offer |
call:waiting | server → caller | { paraId, reason: 'offline' } | Callee’s socket room is empty; call stored as pending |
call:unavailable | server → caller | { paraId, reason: string } | Call rejected server-side (no mutual match: reason: 'no_match') |
call:accept | client → server | { paraId, signalData } | Callee accepts; signalData is the SDP answer |
call:accepted | server → caller | { signalData, answererId } | Forwarded SDP answer to the original caller |
call:reject | client → server | { paraId } | Callee declines the call |
call:rejected | server → caller | { fromId } | Notifies the caller that the call was declined |
call:signal | client → server | { paraId, signalData } | Relay ICE candidates or renegotiation signals |
call:signal | server → peer | { fromId, signalData } | Forwarded ICE/signal to the other peer |
call:end | client → server | { paraId } | Hang up an active or pending call |
call:ended | server → peer | { fromId } | Notifies the peer that the call was ended |
call:audio-chunk | client → server | { paraId, audioData, chunkIndex } | Audio relay fallback for environments without native WebRTC |
call:audio-chunk | server → recipient | { fromId, audioData, chunkIndex } | Forwarded audio chunk to the recipient |
call:cancel_pending | client → server | { paraId } | Cancel a stored pending call before the callee reconnects |
Call flow (happy path)
Caller emits call:request
The caller creates an SDP offer via WebRTC and emits it as
signalData. The server checks for a mutual match; if none exists, it emits call:unavailable back to the caller.Server forwards to callee or stores as pending
If the callee’s socket room has active connections, the server emits
call:incoming immediately. If the room is empty (callee is offline), the call is stored in memory and call:waiting is sent to the caller.Callee receives call:incoming
The callee’s app shows an incoming call UI, plays the ringtone, and waits for user action.
Callee emits call:accept
On acceptance, the callee creates an SDP answer and emits it as
signalData in call:accept.Server forwards call:accepted to caller
The caller receives the SDP answer and sets it as the remote description.
ICE candidate exchange via call:signal
Both peers exchange ICE candidates through
call:signal until a working connection path is established.Example — initiate and accept a call
Using the socket from the React Native app
The mobile app wraps the socket connection in a context provider. Use theuseSocket() hook to access the shared socket instance:
SocketProvider in SocketContext.tsx manages the connection lifecycle automatically:
- Reads
access_token,user_name, anduser_photofromAsyncStorageon mount. - Reconnects when the app returns to the foreground (
AppStatelistener). - Polls every 3 seconds until a token is available (handles the case where the socket mounts before login completes).
- Re-exposes a
reconnect()function for forcing a fresh connection after login or logout.
useCall() hook from CallContext.tsx, which wraps useWebRTC and handles the full incoming/outgoing call lifecycle including SDP negotiation, ringtone playback, and navigation to the call screen.
Pending calls have a 60-second TTL. If a caller initiates a call while the callee
is offline, the server stores the call data in memory. When the callee reconnects
within 60 seconds,
call:incoming is delivered immediately on connection. If more
than 60 seconds pass before reconnection, the pending call is discarded and never
delivered. The caller can also cancel a pending call early by emitting
call:cancel_pending.