> ## Documentation Index
> Fetch the complete documentation index at: https://docs.perplexity.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# System Status

export const ApiStatus = () => {
  const STATUS_API_URL = 'https://status.perplexity.com/api/v1/summary';
  const STATUS_PAGE_URL = 'https://status.perplexity.com/';
  const API_COMPONENT_NAME = 'api';
  const STATUS_CONFIGS = {
    operational: {
      text: 'Operational',
      color: '#10b981',
      bgColor: 'rgba(16, 185, 129, 0.1)',
      icon: '✓',
      rank: 0
    },
    under_maintenance: {
      text: 'Under Maintenance',
      color: '#6b7280',
      bgColor: 'rgba(107, 114, 128, 0.1)',
      icon: '🔧',
      rank: 1
    },
    degraded_performance: {
      text: 'Degraded Performance',
      color: '#f59e0b',
      bgColor: 'rgba(245, 158, 11, 0.1)',
      icon: '⚠',
      rank: 2
    },
    partial_outage: {
      text: 'Partial Outage',
      color: '#f59e0b',
      bgColor: 'rgba(245, 158, 11, 0.1)',
      icon: '⚠',
      rank: 3
    },
    full_outage: {
      text: 'Major Outage',
      color: '#dc2626',
      bgColor: 'rgba(220, 38, 38, 0.1)',
      icon: '✗',
      rank: 4
    }
  };
  const UNKNOWN_STATUS_CONFIG = {
    text: 'Unknown',
    color: '#6b7280',
    bgColor: 'rgba(107, 114, 128, 0.1)',
    icon: '?'
  };
  const formatStatus = value => {
    if (typeof value !== 'string') return 'Unknown';
    return value.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
  };
  const affectsApi = event => event.affected_components.some(component => component.name.trim().toLowerCase() === API_COMPONENT_NAME);
  const validateEvents = events => {
    if (!Array.isArray(events)) throw new Error('Invalid status response');
    events.forEach(event => {
      if (!event || !Array.isArray(event.affected_components)) {
        throw new Error('Invalid status event');
      }
      event.affected_components.forEach(component => {
        if (!component || typeof component.name !== 'string') {
          throw new Error('Invalid affected component');
        }
      });
    });
    return events.filter(affectsApi);
  };
  const parseStatus = summary => {
    if (!summary || typeof summary !== 'object') {
      throw new Error('Invalid status response');
    }
    const incidents = validateEvents(summary.ongoing_incidents);
    const inProgressMaintenances = validateEvents(summary.in_progress_maintenances);
    const scheduledMaintenances = validateEvents(summary.scheduled_maintenances);
    const activeEvents = [...incidents, ...inProgressMaintenances];
    const impacts = activeEvents.map(event => event.current_worst_impact);
    if (impacts.some(impact => !STATUS_CONFIGS[impact])) {
      return {
        api: null,
        incidents,
        maintenances: [...inProgressMaintenances, ...scheduledMaintenances]
      };
    }
    const api = impacts.reduce((worst, impact) => STATUS_CONFIGS[impact].rank > STATUS_CONFIGS[worst].rank ? impact : worst, 'operational');
    return {
      api,
      incidents,
      maintenances: [...inProgressMaintenances, ...scheduledMaintenances]
    };
  };
  const getEventName = event => typeof event.name === 'string' && event.name.trim() ? event.name : 'API status event';
  const [status, setStatus] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [lastUpdated, setLastUpdated] = useState(null);
  const fetchStatus = async () => {
    try {
      setLoading(true);
      setError(null);
      const response = await fetch(STATUS_API_URL);
      if (!response.ok) throw new Error('Failed to fetch status data');
      const summary = await response.json();
      setStatus(parseStatus(summary));
      setLastUpdated(new Date());
    } catch {
      setStatus(null);
      setLastUpdated(null);
      setError('Status unavailable');
    } finally {
      setLoading(false);
    }
  };
  useEffect(() => {
    fetchStatus();
    const interval = setInterval(fetchStatus, 5 * 60 * 1000);
    return () => clearInterval(interval);
  }, []);
  const formatTime = date => {
    if (!date) return '';
    const now = new Date();
    const diff = Math.floor((now - date) / 1000);
    if (diff < 60) return 'Just now';
    if (diff < 3600) return `${Math.floor(diff / 60)} minutes ago`;
    return date.toLocaleTimeString();
  };
  if (loading && !status) {
    return <div className="not-prose my-6 p-6 rounded-lg border border-border bg-card" role="status">
        <div className="flex items-center gap-3">
          <div className="w-3 h-3 rounded-full bg-muted-foreground animate-pulse"></div>
          <span className="text-muted-foreground">Loading API status...</span>
        </div>
      </div>;
  }
  if (error) {
    return <div className="not-prose my-6 p-6 rounded-lg border border-border bg-card" role="status">
        <div className="flex items-center gap-3">
          <span className="text-muted-foreground">{error}</span>
          <button onClick={fetchStatus} className="text-sm text-foreground underline hover:no-underline">
            Retry
          </button>
        </div>
        <a href={STATUS_PAGE_URL} target="_blank" rel="noopener noreferrer" className="text-sm text-muted-foreground hover:text-foreground underline mt-3 inline-block">
          View the full status page →
        </a>
      </div>;
  }
  const apiConfig = status.api ? STATUS_CONFIGS[status.api] : UNKNOWN_STATUS_CONFIG;
  return <div className="not-prose my-6">
      <div className="p-6 rounded-lg border border-border bg-card">
        <div className="flex items-start justify-between mb-4">
          <div>
            <h3 className="text-lg font-semibold text-foreground mb-1">API Status</h3>
            {lastUpdated && <p className="text-sm text-muted-foreground">
                Last updated: {formatTime(lastUpdated)}
              </p>}
          </div>
          <div className="px-3 py-1 rounded-md text-sm font-medium" style={{
    color: apiConfig.color,
    backgroundColor: apiConfig.bgColor
  }}>
            {apiConfig.icon} {apiConfig.text}
          </div>
        </div>
        <div className="flex items-center gap-2">
          <div className="w-3 h-3 rounded-full" style={{
    backgroundColor: apiConfig.color
  }}></div>
          <span className="text-foreground">
            {status.api ? <>The Perplexity API is currently <strong>{apiConfig.text.toLowerCase()}</strong>.</> : <>The current Perplexity API status is <strong>unknown</strong>.</>}
          </span>
        </div>
        {loading && <div className="mt-3 text-xs text-muted-foreground" role="status">Updating...</div>}
      </div>
      {status.incidents.length > 0 && <div className="mt-4 p-6 rounded-lg border border-destructive/20 bg-destructive/5">
          <h4 className="text-base font-semibold text-destructive mb-3">Active API Incidents</h4>
          {status.incidents.map(incident => <div key={incident.id || getEventName(incident)} className="mb-3 last:mb-0">
              <div className="font-medium text-foreground mb-1">{getEventName(incident)}</div>
              <div className="text-sm text-muted-foreground">
                Status: {formatStatus(incident.status)} • Impact: {formatStatus(incident.current_worst_impact)}
              </div>
              {incident.url && <a href={incident.url} target="_blank" rel="noopener noreferrer" className="text-sm text-foreground underline hover:no-underline mt-1 inline-block">
                  View details →
                </a>}
            </div>)}
        </div>}
      {status.maintenances.length > 0 && <div className="mt-4 p-6 rounded-lg border border-warning/20 bg-warning/5">
          <h4 className="text-base font-semibold text-warning mb-3">API Maintenance</h4>
          {status.maintenances.map(maintenance => <div key={maintenance.id || getEventName(maintenance)} className="mb-3 last:mb-0">
              <div className="font-medium text-foreground mb-1">{getEventName(maintenance)}</div>
              <div className="text-sm text-muted-foreground">
                Status: {formatStatus(maintenance.status)}
              </div>
              {maintenance.url && <a href={maintenance.url} target="_blank" rel="noopener noreferrer" className="text-sm text-foreground underline hover:no-underline mt-1 inline-block">
                  View details →
                </a>}
            </div>)}
        </div>}
      <div className="mt-4">
        <a href={STATUS_PAGE_URL} target="_blank" rel="noopener noreferrer" className="text-sm text-muted-foreground hover:text-foreground underline">
          View full status page →
        </a>
      </div>
    </div>;
};

<ApiStatus />

## Contact & Support

If you experience any issues, please reach out through one of the following channels:

<CardGroup cols={2}>
  <Card title="Email Support" icon="mail" href="mailto:api@perplexity.ai">
    Send us an email at **[api@perplexity.ai](mailto:api@perplexity.ai)** for enterprise inquiries or bug reports.
  </Card>

  <Card title="Discord Community" icon="message-circle" href="https://discord.com/invite/perplexity-ai">
    Join our Discord community to discuss with other developers and flag bug reports.
  </Card>
</CardGroup>
