ProductFlo API Quickstart

This guide will help you get started with the ProductFlo API, focusing on the real-time WebSocket functionality. You’ll learn how to connect, authenticate, send messages, and handle responses.

Authentication

Before using the API, you need to authenticate:

// Get an authentication token
const response = await fetch('https://api.productflo.io/auth/login', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'your-email@example.com',
    password: 'your-password',
  }),
});

const { token } = await response.json();

WebSocket Connection

Connect to the WebSocket API

// Connect with authentication token
const socket = new WebSocket(`wss://api.productflo.io/ws?token=${token}`);

// For anonymous connections (no authentication)
const socket = new WebSocket('wss://api.productflo.io/ws');

// Handle connection events
socket.onopen = () => {
  console.log('Connected to ProductFlo WebSocket API');
};

socket.onclose = (event) => {
  console.log('Disconnected from ProductFlo WebSocket API', event.code, event.reason);
};

socket.onerror = (error) => {
  console.error('WebSocket error:', error);
};

Handle Messages

socket.onmessage = (event) => {
  const message = JSON.parse(event.data);
  
  // Handle different message types
  switch(message.type) {
    case 'chat':
      handleChatMessage(message);
      break;
    case 'system':
      handleSystemMessage(message);
      break;
    case 'error':
      handleErrorMessage(message);
      break;
    case 'presence':
      handlePresenceUpdate(message);
      break;
    default:
      console.log('Received message:', message);
  }
};

function handleChatMessage(message) {
  console.log(`${message.data.sender}: ${message.data.message}`);
}

function handleSystemMessage(message) {
  console.log(`System: ${message.data.message}`);
}

function handleErrorMessage(message) {
  console.error(`Error (${message.data.code}): ${message.data.message}`);
}

function handlePresenceUpdate(message) {
  console.log(`User ${message.data.user_id} is now ${message.data.status}`);
}

Send Messages

Join a Room

socket.send(JSON.stringify({
  type: 'join',
  room_id: 'product-123'
}));

Send a Chat Message

socket.send(JSON.stringify({
  type: 'chat',
  room_id: 'product-123',
  task: 'direct_chat',
  data: {
    message: 'Hello team!',
    sender: 'user-456'
  }
}));

Request AI-Generated Content

socket.send(JSON.stringify({
  type: 'chat',
  task: 'image_generation',
  data: {
    message: 'Generate a 3D model of a smartphone with a foldable display',
    sender: 'user-456',
    product_id: 'product-123'
  }
}));

Advanced Usage

Room-Based Communication

ProductFlo uses rooms for efficient message routing:

// Join a room
socket.send(JSON.stringify({
  type: 'join',
  room_id: 'product-123'
}));

// Send a message to the room
socket.send(JSON.stringify({
  type: 'chat',
  room_id: 'product-123',
  data: {
    message: 'Let\'s discuss the new design',
    sender: 'user-456'
  }
}));

// Leave a room
socket.send(JSON.stringify({
  type: 'leave',
  room_id: 'product-123'
}));

Presence Updates

Track when users come online or go offline:

// Update your status
socket.send(JSON.stringify({
  type: 'presence',
  data: {
    status: 'online',  // 'online', 'away', 'busy', 'offline'
    last_active: new Date().toISOString()
  }
}));

Error Handling

Handle errors from the WebSocket API:

socket.onmessage = (event) => {
  const message = JSON.parse(event.data);
  
  if (message.type === 'error') {
    const { code, message: errorMessage, details } = message.data;
    
    switch (code) {
      case 'INVALID_FORMAT':
        console.error('The message format is invalid:', errorMessage);
        break;
      case 'VALIDATION_ERROR':
        console.error('Message validation failed:', details.errors);
        break;
      case 'PROCESSING_ERROR':
        console.error('Server failed to process the message:', errorMessage);
        break;
      default:
        console.error(`Error (${code}):`, errorMessage);
    }
  }
};

Framework-Specific Examples

import { useEffect, useState } from 'react';

function WebSocketComponent() {
  const [socket, setSocket] = useState(null);
  const [messages, setMessages] = useState([]);
  
  useEffect(() => {
    // Create WebSocket connection
    const ws = new WebSocket('wss://api.productflo.io/ws');
    
    ws.onopen = () => {
      console.log('Connected to WebSocket');
      setSocket(ws);
    };
    
    ws.onmessage = (event) => {
      const message = JSON.parse(event.data);
      setMessages((prev) => [...prev, message]);
    };
    
    ws.onclose = () => {
      console.log('Disconnected from WebSocket');
    };
    
    // Clean up on unmount
    return () => {
      ws.close();
    };
  }, []);
  
  const sendMessage = (text) => {
    if (socket && socket.readyState === WebSocket.OPEN) {
      socket.send(JSON.stringify({
        type: 'chat',
        room_id: 'react-room',
        data: {
          message: text,
          sender: 'react-user'
        }
      }));
    }
  };
  
  return (
    <div>
      <h1>ProductFlo WebSocket Chat</h1>
      <div>
        {messages.map((msg, index) => (
          <div key={index}>
            {msg.data?.sender}: {msg.data?.message}
          </div>
        ))}
      </div>
      <button onClick={() => sendMessage('Hello from React!')}>
        Send Message
      </button>
    </div>
  );
}

Next Steps