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

# Models

> All AI models available on Samurai AI — live data, real pricing at 50% off provider rates.

<Note>
  Prices shown are **Samurai AI prices (50% off provider rates)**. Base URL: `https://www.samuraiapi.in/v1`
</Note>

/*Search bar*/
/*Provider tabs — wrap, no overflow*/
/*Stats row*/
/*Loading*/
/*Error*/
/*Model list — card rows, no table, no horizontal scroll*/
/*Header row*/
/*Model rows*/
/*Model ID + badges*/
/*Context*/
/*Input price*/
/*Output price*/
/*Pagination*/
export const ModelsCatalog = () => {
  const [models, setModels] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [search, setSearch] = React.useState('');
  const [tab, setTab] = React.useState('all');
  const [providers, setProviders] = React.useState([]);
  const [copied, setCopied] = React.useState(null);
  const [page, setPage] = React.useState(1);
  const [total, setTotal] = React.useState(0);
  const PER_PAGE = 50;
  const fetchModels = React.useCallback(async (p = 1) => {
    setLoading(true);
    setError(null);
    try {
      const params = new URLSearchParams({
        limit: String(PER_PAGE),
        page: String(p)
      });
      if (tab !== 'all') params.set('provider', tab);
      if (search.trim()) params.set('search', search.trim());
      const res = await fetch(`https://www.samuraiapi.in/api/public/models?${params.toString()}`);
      if (!res.ok) throw new Error(`HTTP ${res.status}`);
      const json = await res.json();
      if (!json.success) throw new Error(json.error || 'Failed to load');
      setModels(json.data || []);
      setTotal(json.pagination?.total || 0);
      if (json.providers?.length) setProviders(json.providers);
    } catch (e) {
      setError(e.message);
    } finally {
      setLoading(false);
    }
  }, [tab, search, PER_PAGE]);
  React.useEffect(() => {
    setPage(1);
    fetchModels(1);
  }, [tab, search]);
  React.useEffect(() => {
    fetchModels(page);
  }, [page]);
  const copyId = async id => {
    try {
      await navigator.clipboard.writeText(id);
      setCopied(id);
      setTimeout(() => setCopied(null), 1500);
    } catch (_) {}
  };
  const fmtCtx = v => {
    if (!v) return '—';
    const n = parseInt(v);
    if (isNaN(n)) return v;
    if (n >= 1000000) return `${(n / 1000000).toFixed(0)}M`;
    if (n >= 1000) return `${(n / 1000).toFixed(0)}K`;
    return String(n);
  };
  const fmtPrice = v => {
    if (!v && v !== 0) return '—';
    const n = parseFloat(v);
    if (isNaN(n) || n === 0) return 'Free';
    if (n < 0.01) return `$${n.toFixed(4)}`;
    return `$${n.toFixed(3)}`;
  };
  const providerColor = p => {
    const map = {
      openai: {
        bg: '#d1fae5',
        text: '#065f46'
      },
      anthropic: {
        bg: '#fce7f3',
        text: '#9d174d'
      },
      google: {
        bg: '#dbeafe',
        text: '#1e40af'
      },
      meta: {
        bg: '#ede9fe',
        text: '#5b21b6'
      },
      mistral: {
        bg: '#fef3c7',
        text: '#92400e'
      },
      deepseek: {
        bg: '#f0fdf4',
        text: '#166534'
      },
      xai: {
        bg: '#f3f4f6',
        text: '#374151'
      },
      cohere: {
        bg: '#fff7ed',
        text: '#c2410c'
      }
    };
    return map[(p || '').toLowerCase()] || ({
      bg: '#f3f4f6',
      text: '#374151'
    });
  };
  const typeIcon = t => {
    const icons = {
      chat: '💬',
      audio: '🔊',
      embedding: '🔢',
      image: '🖼️',
      video: '🎬'
    };
    return icons[(t || '').toLowerCase()] || '🤖';
  };
  const tabs = [{
    key: 'all',
    label: `All (${total || models.length})`
  }, ...providers.slice(0, 8).map(p => ({
    key: p.name.toLowerCase(),
    label: `${p.name} (${p.count})`
  }))];
  const totalPages = Math.ceil(total / PER_PAGE);
  return <div style={{
    width: '100%',
    maxWidth: '100%',
    overflowX: 'hidden'
  }}>

      {}
      <div style={{
    position: 'relative',
    marginBottom: '0.75rem'
  }}>
        <input type="text" placeholder="Search models by ID or name..." value={search} onChange={e => setSearch(e.target.value)} style={{
    width: '100%',
    padding: '0.6rem 0.85rem',
    borderRadius: '8px',
    border: '1px solid #e5e7eb',
    fontSize: '0.875rem',
    boxSizing: 'border-box',
    outline: 'none'
  }} />
      </div>

      {}
      <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: '0.4rem',
    marginBottom: '1rem'
  }}>
        {tabs.map(t => <button key={t.key} onClick={() => setTab(t.key)} style={{
    padding: '0.25rem 0.65rem',
    borderRadius: '9999px',
    border: 'none',
    cursor: 'pointer',
    fontSize: '0.75rem',
    fontWeight: 500,
    whiteSpace: 'nowrap',
    background: tab === t.key ? '#4F46E5' : '#f3f4f6',
    color: tab === t.key ? 'white' : '#374151',
    transition: 'all 0.15s'
  }}>
            {t.label}
          </button>)}
      </div>

      {}
      {!loading && !error && <div style={{
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginBottom: '0.75rem',
    flexWrap: 'wrap',
    gap: '0.5rem'
  }}>
          <span style={{
    fontSize: '0.8rem',
    color: '#6b7280'
  }}>
            Showing {models.length} of {total} models • Live from Samurai AI
          </span>
          <button onClick={() => fetchModels(page)} style={{
    fontSize: '0.75rem',
    padding: '0.2rem 0.6rem',
    borderRadius: '6px',
    border: '1px solid #d1d5db',
    cursor: 'pointer',
    background: 'transparent',
    color: '#6b7280'
  }}>
            ↻ Refresh
          </button>
        </div>}

      {}
      {loading && <div style={{
    textAlign: 'center',
    padding: '3rem 1rem',
    color: '#6b7280'
  }}>
          <div style={{
    fontSize: '1.5rem',
    marginBottom: '0.5rem'
  }}>⏳</div>
          <p style={{
    margin: 0,
    fontSize: '0.875rem'
  }}>Loading models from Samurai AI...</p>
        </div>}

      {}
      {!loading && error && <div style={{
    padding: '1rem',
    borderRadius: '8px',
    background: '#fef2f2',
    border: '1px solid #fecaca',
    marginBottom: '1rem'
  }}>
          <p style={{
    margin: '0 0 0.25rem',
    fontWeight: 600,
    fontSize: '0.875rem',
    color: '#991b1b'
  }}>
            ⚠️ Could not load live models
          </p>
          <p style={{
    margin: '0 0 0.5rem',
    fontSize: '0.8rem',
    color: '#b91c1c'
  }}>
            {error} — the API may be temporarily unavailable.
          </p>
          <button onClick={() => fetchModels(page)} style={{
    fontSize: '0.8rem',
    padding: '0.3rem 0.75rem',
    borderRadius: '6px',
    border: 'none',
    background: '#4F46E5',
    color: 'white',
    cursor: 'pointer'
  }}>
            Retry
          </button>
        </div>}

      {}
      {!loading && !error && <>
          {models.length === 0 ? <p style={{
    textAlign: 'center',
    color: '#6b7280',
    padding: '2rem'
  }}>
              No models match your search.
            </p> : <div style={{
    display: 'flex',
    flexDirection: 'column',
    gap: '0.4rem'
  }}>
              {}
              <div style={{
    display: 'grid',
    gridTemplateColumns: '1fr auto auto auto',
    gap: '0.5rem',
    padding: '0.4rem 0.75rem',
    borderRadius: '6px',
    background: '#f9fafb',
    fontSize: '0.7rem',
    fontWeight: 600,
    color: '#9ca3af',
    textTransform: 'uppercase',
    letterSpacing: '0.05em'
  }}>
                <span>Model ID</span>
                <span style={{
    textAlign: 'center'
  }}>Context</span>
                <span style={{
    textAlign: 'right'
  }}>In $/1M</span>
                <span style={{
    textAlign: 'right'
  }}>Out $/1M</span>
              </div>

              {}
              {models.map(m => {
    const color = providerColor(m.provider);
    return <div key={m.id} style={{
      display: 'grid',
      gridTemplateColumns: '1fr auto auto auto',
      gap: '0.5rem',
      alignItems: 'center',
      padding: '0.6rem 0.75rem',
      borderRadius: '8px',
      border: '1px solid #f3f4f6',
      background: 'white',
      transition: 'border-color 0.15s'
    }}>
                    {}
                    <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.4rem',
      minWidth: 0,
      overflow: 'hidden'
    }}>
                      <span style={{
      fontSize: '0.875rem'
    }}>{typeIcon(m.type)}</span>
                      <code onClick={() => copyId(m.id)} title="Click to copy" style={{
      fontSize: '0.78rem',
      fontFamily: 'monospace',
      background: '#f3f4f6',
      padding: '0.15rem 0.35rem',
      borderRadius: '4px',
      cursor: 'pointer',
      overflow: 'hidden',
      textOverflow: 'ellipsis',
      whiteSpace: 'nowrap',
      maxWidth: '100%',
      display: 'block',
      border: copied === m.id ? '1px solid #4F46E5' : '1px solid transparent',
      color: copied === m.id ? '#4F46E5' : 'inherit'
    }}>
                        {copied === m.id ? '✓ Copied!' : m.id}
                      </code>
                      <span style={{
      fontSize: '0.65rem',
      padding: '0.1rem 0.4rem',
      borderRadius: '9999px',
      background: color.bg,
      color: color.text,
      fontWeight: 600,
      whiteSpace: 'nowrap',
      flexShrink: 0
    }}>
                        {m.provider}
                      </span>
                      {m.isNew && <span style={{
      fontSize: '0.6rem',
      padding: '0.1rem 0.35rem',
      borderRadius: '9999px',
      background: '#dbeafe',
      color: '#1d4ed8',
      fontWeight: 700,
      flexShrink: 0
    }}>
                          NEW
                        </span>}
                    </div>

                    {}
                    <span style={{
      fontSize: '0.75rem',
      color: '#6b7280',
      whiteSpace: 'nowrap',
      textAlign: 'center'
    }}>
                      {fmtCtx(m.contextWindow)}
                    </span>

                    {}
                    <span style={{
      fontSize: '0.75rem',
      fontWeight: 600,
      color: '#059669',
      whiteSpace: 'nowrap',
      textAlign: 'right'
    }}>
                      {fmtPrice(m.inputPrice)}
                    </span>

                    {}
                    <span style={{
      fontSize: '0.75rem',
      fontWeight: 600,
      color: '#d97706',
      whiteSpace: 'nowrap',
      textAlign: 'right'
    }}>
                      {fmtPrice(m.outputPrice)}
                    </span>
                  </div>;
  })}
            </div>}

          {}
          {totalPages > 1 && <div style={{
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: '0.5rem',
    marginTop: '1rem',
    flexWrap: 'wrap'
  }}>
              <button disabled={page <= 1} onClick={() => setPage(p => Math.max(1, p - 1))} style={{
    padding: '0.3rem 0.75rem',
    borderRadius: '6px',
    border: '1px solid #d1d5db',
    cursor: page <= 1 ? 'not-allowed' : 'pointer',
    background: 'transparent',
    fontSize: '0.8rem',
    opacity: page <= 1 ? 0.4 : 1
  }}>
                ← Prev
              </button>
              <span style={{
    fontSize: '0.8rem',
    color: '#6b7280'
  }}>
                Page {page} of {totalPages}
              </span>
              <button disabled={page >= totalPages} onClick={() => setPage(p => Math.min(totalPages, p + 1))} style={{
    padding: '0.3rem 0.75rem',
    borderRadius: '6px',
    border: '1px solid #d1d5db',
    cursor: page >= totalPages ? 'not-allowed' : 'pointer',
    background: 'transparent',
    fontSize: '0.8rem',
    opacity: page >= totalPages ? 0.4 : 1
  }}>
                Next →
              </button>
            </div>}
        </>}
    </div>;
};


## Live Model Catalog

<ModelsCatalog />

***

## List Models via API

```bash cURL theme={null}
curl https://www.samuraiapi.in/v1/models \
  -H "Authorization: Bearer sk-samurai-YOUR_KEY"
```

```python Python theme={null}
models = client.models.list()
for model in models.data:
    print(model.id)
```

***

## Audio Models

| Model ID    | Use Case                  | Price           |
| ----------- | ------------------------- | --------------- |
| `tts-1`     | Text to Speech (standard) | \$3.75/1M chars |
| `tts-1-hd`  | Text to Speech (HD)       | \$7.50/1M chars |
| `whisper-1` | Speech to Text            | \$0.003/minute  |

## Embedding Models

| Model ID                 | Dimensions | Price             |
| ------------------------ | ---------- | ----------------- |
| `text-embedding-3-small` | 1536       | \$0.01/1M tokens  |
| `text-embedding-3-large` | 3072       | \$0.065/1M tokens |
| `text-embedding-ada-002` | 1536       | \$0.05/1M tokens  |

<Card title="View Pricing Details" icon="tag" href="/reference/pricing">
  Full pricing breakdown for all model tiers.
</Card>
