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

# xAI Grok models

> Connect xAI to ModuleX with your own API key, see the available Grok models, and understand how BYOK usage is billed.

export const MediaEmbed = ({id, type = 'screenshot', caption = '', ext, ratio = '16 / 9'}) => {
  const isVideo = type === 'video' || type === 'app_video';
  const resolvedExt = ext || (isVideo ? 'mp4' : type === 'screenshot' ? 'webp' : 'svg');
  const src = 'https://media.modulex.dev/' + id + '.' + resolvedExt;
  const [status, setStatus] = useState('loading');
  const [isDev, setIsDev] = useState(false);
  const [inView, setInView] = useState(false);
  const boxRef = useRef(null);
  useEffect(() => {
    if (typeof window === 'undefined') return;
    const h = window.location.hostname;
    setIsDev(h === 'localhost' || h === '127.0.0.1' || h.endsWith('.mintlify.app'));
  }, []);
  useEffect(() => {
    if (inView) return;
    if (typeof IntersectionObserver === 'undefined') {
      setInView(true);
      return;
    }
    const el = boxRef.current;
    if (!el) return;
    const io = new IntersectionObserver(entries => {
      if (entries.some(e => e.isIntersecting)) {
        setInView(true);
        io.disconnect();
      }
    }, {
      rootMargin: '300px'
    });
    io.observe(el);
    return () => io.disconnect();
  }, [inView]);
  if (status === 'missing') {
    if (!isDev) return null;
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      justifyContent: 'center',
      gap: '0.4rem',
      padding: '1rem 1.25rem',
      margin: '1.25rem 0',
      width: '100%',
      aspectRatio: ratio,
      boxSizing: 'border-box',
      border: '1px dashed rgba(128,128,128,0.45)',
      borderRadius: '0.75rem',
      background: 'rgba(128,128,128,0.06)',
      color: 'currentColor',
      fontSize: '0.85rem',
      lineHeight: 1.45
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '0.5rem',
      opacity: 0.75
    }}>
          <span aria-hidden="true">🎬</span>
          <code style={{
      fontSize: '0.75rem'
    }}>{id}</code>
          <span style={{
      fontSize: '0.65rem',
      textTransform: 'uppercase',
      letterSpacing: '0.04em',
      padding: '0.1rem 0.4rem',
      borderRadius: '0.4rem',
      background: 'rgba(128,128,128,0.18)'
    }}>
            {type}
          </span>
        </div>
        <div style={{
      opacity: 0.9
    }}>{caption || 'Media not uploaded yet.'}</div>
        <div style={{
      fontSize: '0.7rem',
      opacity: 0.5
    }}>
          Upload to R2 as <code>{id}.{resolvedExt}</code> — preview only, hidden in production.
        </div>
      </div>;
  }
  const mediaStyle = {
    display: status === 'loaded' ? 'block' : 'none',
    width: '100%',
    height: 'auto',
    borderRadius: '0.75rem'
  };
  const media = isVideo ? <video src={inView ? src : undefined} autoPlay loop muted playsInline preload="metadata" onLoadedData={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} /> : <img src={inView ? src : undefined} alt={caption} onLoad={() => setStatus('loaded')} onError={() => setStatus('missing')} style={mediaStyle} />;
  return <figure style={{
    margin: '1.25rem 0'
  }}>
      <div ref={boxRef} style={status === 'loaded' ? {
    width: '100%'
  } : {
    width: '100%',
    aspectRatio: ratio,
    borderRadius: '0.75rem',
    background: 'rgba(128,128,128,0.06)'
  }}>
        {media}
      </div>
      {status === 'loaded' && caption ? <figcaption style={{
    marginTop: '0.5rem',
    textAlign: 'center',
    fontSize: '0.85rem',
    opacity: 0.7
  }}>
          {caption}
        </figcaption> : null}
    </figure>;
};

xAI is a [BYOK (bring-your-own-key)](/reference/glossary) LLM provider in ModuleX. You connect your own xAI API key, then use Grok models in the [LLM node](/workflow-builder/nodes/llm), the [Agent node](/workflow-builder/nodes/agent), [chat](/platform/chat/model-selection), and the [Assistant](/assistant/models-and-settings). Because xAI is BYOK, xAI bills you directly for token usage and ModuleX adds no credit charge on top — see [BYOK billing](#byok-billing) below.

For the full list of provider types and how managed versus BYOK selection works, see [LLM providers](/integrations/llm-providers/overview). If you would rather have ModuleX provision and meter the model for you in credits, use [ModuleX-managed models](/integrations/llm-providers/modulexai) instead.

<MediaEmbed id="MX-MEDIA-4090" type="screenshot" caption={"The xAI connection card in the ModuleX integrations/credentials UI."} />

## What you need

<Steps>
  <Step title="An xAI API key">
    Create a key in the [xAI Console](https://console.x.ai/team) under **API Keys → Create new API key**. xAI keys start with `xai-` (for example `xai-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`). ModuleX validates the key against the pattern `^xai-[a-zA-Z0-9\-_]{20,}$` before saving it.
  </Step>

  <Step title="A ModuleX organization and an owner/admin role">
    Credentials are scoped to an [organization](/concepts/organizations-roles). Connecting and managing integrations requires the **owner** or **admin** role — the `member` role is retired. See [roles & permissions](/security/roles-permissions).
  </Step>

  <Step title="A ModuleX API key (for programmatic setup)">
    To connect xAI over the API or an SDK, you need a ModuleX API key (`mx_live_…`) and your organization id. See [authentication](/api-reference/authentication).
  </Step>
</Steps>

## Connect xAI

You connect xAI by storing your xAI API key as a [credential](/integrations/managing-credentials) for the `xai` integration. You can do this in the app or programmatically.

### In the app

1. Open the [integrations catalog](/integrations/catalog) and select **xAI**, or open **Settings → Credentials**.
2. Choose **API Key Authentication** and paste your xAI key.
3. Optionally set a custom **Base URL** (defaults to `https://api.x.ai/v1`) — only needed for xAI-compatible gateways.
4. Save. ModuleX validates the key with a minimal request before storing it (see [Test a key before saving](#test-a-key-before-saving)).

xAI exposes a single authentication scheme — `api_key`. Its fields are:

<ParamField path="api_key" type="string" required>
  Your xAI API key. Stored encrypted and never returned in plaintext. Pattern `^xai-[a-zA-Z0-9\-_]{20,}$`; sample format `xai-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`.
</ParamField>

<ParamField path="base_url" type="string" default="https://api.x.ai/v1">
  Optional custom API base URL, only needed when pointing at an xAI-compatible API. Must match `^https?://.*`.
</ParamField>

### Over the API or an SDK

Create the credential with `POST /credentials`. ModuleX detects the credential type from the body: an `auth_data.api_key` value is stored as an `api_key` credential. Set `make_default: true` to make this the default xAI credential for the organization.

Every request authenticates with `Authorization: Bearer mx_live_…` plus the `X-Organization-ID` header (see [authentication](/api-reference/authentication)).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modulex.dev/credentials \
    -H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
    -H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
    -H "Content-Type: application/json" \
    -d '{
          "integration_name": "xai",
          "display_name": "xAI production key",
          "make_default": true,
          "auth_data": { "api_key": "xai-..." }
        }'
  ```

  ```python Python theme={null}
  import asyncio
  from modulex import Modulex

  async def main():
      async with Modulex(
          api_key="mx_live_xxxxxxxxxxxxxxxxxxxxxxxx",   # or MODULEX_API_KEY
          organization_id="6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
      ) as client:
          cred = await client.credentials.create(
              integration_name="xai",
              display_name="xAI production key",
              make_default=True,
              auth_data={"api_key": "xai-..."},
          )
          print(cred.id)

  asyncio.run(main())
  ```

  ```javascript JavaScript theme={null}
  import { Modulex } from "modulex-js";

  const client = new Modulex({
    apiKey: "mx_live_xxxxxxxxxxxxxxxxxxxxxxxx",         // or process.env.MODULEX_API_KEY
    organizationId: "6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
  });

  const cred = await client.credentials.create({
    integration_name: "xai",
    display_name: "xAI production key",
    make_default: true,
    auth_data: { api_key: "xai-..." },
  });
  console.log(cred.id);
  ```
</CodeGroup>

<ResponseField name="id" type="string">
  The new credential's identifier. A `201` response returns the credential metadata; the secret is never echoed back.
</ResponseField>

<Note>
  Creating, listing, and managing credentials and the integration catalog requires the **owner** or **admin** role in the organization. A caller without that role receives a `403`. The integration-catalog read routes (for example `GET /integrations/llm-providers/xai`) are also owner/admin-gated.
</Note>

### Test a key before saving

Use `POST /credentials/test-temporary` to validate an xAI key without storing it. ModuleX runs the provider's test call — a 10-token `POST` to `https://api.x.ai/v1/chat/completions` against `grok-4-fast` — and reports success when the response status is `200` and includes the fields `id`, `choices`, and `model`.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.modulex.dev/credentials/test-temporary \
    -H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
    -H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f" \
    -H "Content-Type: application/json" \
    -d '{
          "integration_name": "xai",
          "auth_type": "api_key",
          "auth_data": { "api_key": "xai-..." }
        }'
  ```

  ```python Python theme={null}
  result = await client.credentials.test_temporary(
      integration_name="xai",
      auth_type="api_key",
      auth_data={"api_key": "xai-..."},
  )
  print(result.is_valid, result.status_code)
  ```

  ```javascript JavaScript theme={null}
  const result = await client.credentials.testTemporary({
    integration_name: "xai",
    auth_type: "api_key",
    auth_data: { api_key: "xai-..." },
  });
  console.log(result.is_valid, result.status_code);
  ```
</CodeGroup>

<ResponseField name="is_valid" type="boolean">
  `true` when the test call succeeds.
</ResponseField>

<ResponseField name="status_code" type="integer">
  The HTTP status returned by xAI's test endpoint (`200` on success).
</ResponseField>

<ResponseField name="test_method" type="string">
  How the credential was validated. For xAI this is `api_call`.
</ResponseField>

<ResponseField name="cost_level" type="string">
  The cost class of the test call. For xAI this is `minimal` (a 10-token request).
</ResponseField>

## Available models

ModuleX serves Grok models from the catalog at `GET /integrations/llm-providers/xai`. The catalog is read-only metadata used by the credential UI and the builder — it is not the execution path. The models below are the ones ModuleX currently advertises for xAI.

| Model id           | Display name   | Max input tokens | Max output tokens | Vision | Input \$/1M | Output \$/1M |
| ------------------ | -------------- | ---------------- | ----------------- | ------ | ----------- | ------------ |
| `grok-4-0709`      | Grok 4         | 256,000          | 256,000           | Yes    | `$3.00`     | `$15.00`     |
| `grok-code-fast-1` | Grok Code Fast | 256,000          | 10,000            | No     | `$0.20`     | `$1.50`      |
| `grok-4-fast`      | Grok 4 Fast    | 2,000,000        | 30,000            | Yes    | `$0.20`     | `$0.50`      |

<Note>
  Prices in the table are **xAI's per-token rates** as recorded in the ModuleX catalog, in USD per 1,000,000 tokens. Because xAI is BYOK, these are the rates xAI charges you directly — they are not ModuleX credits. See [BYOK billing](#byok-billing).
</Note>

Each model id is the catalog id you select in the app and in node configuration. ModuleX maps the catalog id to the underlying xAI wire model and request settings:

<Expandable title="Grok 4 — full catalog fields">
  <ResponseField name="id" type="string">`grok-4-0709` — the catalog id you select.</ResponseField>
  <ResponseField name="display_name" type="string">`Grok 4`</ResponseField>
  <ResponseField name="provider" type="string">`xAI`</ResponseField>
  <ResponseField name="provider_id" type="string">`xai` — the routing provider slug.</ResponseField>
  <ResponseField name="max_input_tokens" type="integer">`256000`</ResponseField>
  <ResponseField name="max_output_tokens" type="integer">`256000`</ResponseField>
  <ResponseField name="supports_vision" type="boolean">`true`</ResponseField>
  <ResponseField name="intelligence" type="integer">`5` (quality score, 1–5).</ResponseField>
  <ResponseField name="speed" type="integer">`3` (latency score, 1–5; higher is faster).</ResponseField>
  <ResponseField name="data_freshness" type="string">`2024-10-01` (knowledge cutoff).</ResponseField>
  <ResponseField name="input_usd_per_1m_tokens" type="number">`3.0`</ResponseField>
  <ResponseField name="output_usd_per_1m_tokens" type="number">`15.0`</ResponseField>

  <ResponseField name="wire model" type="string">
    ModuleX sends the wire model `grok-4-0709`.
  </ResponseField>
</Expandable>

<Expandable title="Grok Code Fast — full catalog fields">
  <ResponseField name="id" type="string">`grok-code-fast-1`</ResponseField>
  <ResponseField name="display_name" type="string">`Grok Code Fast`</ResponseField>
  <ResponseField name="provider" type="string">`xAI`</ResponseField>
  <ResponseField name="provider_id" type="string">`xai`</ResponseField>
  <ResponseField name="max_input_tokens" type="integer">`256000`</ResponseField>
  <ResponseField name="max_output_tokens" type="integer">`10000`</ResponseField>
  <ResponseField name="supports_vision" type="boolean">`false`</ResponseField>
  <ResponseField name="intelligence" type="integer">`4`</ResponseField>
  <ResponseField name="speed" type="integer">`3`</ResponseField>
  <ResponseField name="data_freshness" type="string">`2024-10-01`</ResponseField>
  <ResponseField name="input_usd_per_1m_tokens" type="number">`0.2`</ResponseField>
  <ResponseField name="output_usd_per_1m_tokens" type="number">`1.5`</ResponseField>

  <ResponseField name="wire model" type="string">
    Wire model `grok-code-fast-1`. This is a coding-focused model and does not accept image input.
  </ResponseField>
</Expandable>

<Expandable title="Grok 4 Fast — full catalog fields">
  <ResponseField name="id" type="string">`grok-4-fast`</ResponseField>
  <ResponseField name="display_name" type="string">`Grok 4 Fast`</ResponseField>
  <ResponseField name="provider" type="string">`xAI`</ResponseField>
  <ResponseField name="provider_id" type="string">`xai`</ResponseField>
  <ResponseField name="max_input_tokens" type="integer">`2000000`</ResponseField>
  <ResponseField name="max_output_tokens" type="integer">`30000`</ResponseField>
  <ResponseField name="supports_vision" type="boolean">`true`</ResponseField>
  <ResponseField name="intelligence" type="integer">`3`</ResponseField>
  <ResponseField name="speed" type="integer">`4`</ResponseField>
  <ResponseField name="data_freshness" type="string">`2024-10-01`</ResponseField>
  <ResponseField name="input_usd_per_1m_tokens" type="number">`0.2`</ResponseField>
  <ResponseField name="output_usd_per_1m_tokens" type="number">`0.5`</ResponseField>

  <ResponseField name="wire model" type="string">
    Wire model `grok-4-fast`. This is the model ModuleX uses for the connection test.
  </ResponseField>
</Expandable>

<Note>
  The model list is served from the ModuleX catalog and may change as xAI releases or deprecates models. Always read `GET /integrations/llm-providers/xai` for the current set rather than hard-coding ids. Catalog reads are cached for up to 10 minutes.
</Note>

### Read the model catalog

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.modulex.dev/integrations/llm-providers/xai \
    -H "Authorization: Bearer mx_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
    -H "X-Organization-ID: 6f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f"
  ```

  ```python Python theme={null}
  detail = await client.integrations.llm_provider_detail("xai")
  for model in detail.models:
      print(model["id"], model["display_name"])
  ```

  ```javascript JavaScript theme={null}
  const detail = await client.integrations.llmProvider("xai");
  for (const model of detail.models) {
    console.log(model.id, model.display_name);
  }
  ```
</CodeGroup>

The response is an integration-detail object whose `models` array contains the entries shown above, plus an `auth_schemas` array describing the `api_key` scheme. A truncated example:

```json Catalog detail (truncated) theme={null}
{
  "name": "xai",
  "display_name": "xAI",
  "description": "xAI's Grok models for advanced reasoning, coding, and real-time information access",
  "integration_type": "llm_provider",
  "version": "1.0.0",
  "categories": ["AI & LLM Providers", "ai", "chat", "reasoning", "coding"],
  "auth_schemas": [
    {
      "auth_type": "api_key",
      "display_name": "API Key Authentication",
      "description": "Connect using xAI API Key"
    }
  ],
  "models": [
    {
      "id": "grok-4-0709",
      "display_name": "Grok 4",
      "max_input_tokens": 256000,
      "max_output_tokens": 256000,
      "supports_vision": true,
      "input_usd_per_1m_tokens": 3.0,
      "output_usd_per_1m_tokens": 15.0
    }
  ]
}
```

## Use Grok in ModuleX

Once xAI is connected, select a Grok model id wherever a model can be chosen:

<CardGroup cols={2}>
  <Card title="LLM node" icon="message-square" href="/workflow-builder/nodes/llm">
    Call Grok with prompts, variables, and structured output inside a workflow.
  </Card>

  <Card title="Agent node" icon="bot" href="/workflow-builder/nodes/agent">
    Run an autonomous step where Grok can call tools and loop.
  </Card>

  <Card title="Chat" icon="messages-square" href="/platform/chat/model-selection">
    Pick Grok as the model for a chat conversation.
  </Card>

  <Card title="Assistant" icon="sparkles" href="/assistant/models-and-settings">
    Configure the Assistant to reason and act with a Grok model.
  </Card>
</CardGroup>

If your organization holds more than one xAI credential, ModuleX uses the credential marked default for the `xai` integration. Set a different default with `POST /credentials/{credential_id}/set-default`. See [managing credentials](/integrations/managing-credentials).

## BYOK billing

xAI is **bring-your-own-key**, which changes how usage is billed compared with [ModuleX-managed models](/integrations/llm-providers/modulexai).

<CardGroup cols={2}>
  <Card title="BYOK (xAI)" icon="key">
    Token usage is billed by **xAI** against your own API key. ModuleX adds **no credit charge and no markup** for the model call itself. BYOK usage is recorded for analytics only — it does not consume ModuleX [credits](/billing/credits).
  </Card>

  <Card title="Managed (modulexai)" icon="gauge">
    ModuleX provisions the model and bills it in **credits** through the [usage gate](/billing/usage-gating), applying a system margin. Use this when you do not want to manage a provider account.
  </Card>
</CardGroup>

What this means in practice:

* **No ModuleX credit cost for tokens.** A Grok call made with your xAI key is not metered in credits. xAI invoices you directly at its own rates (the per-million-token prices in the [model table](#available-models)).
* **Other ModuleX usage still applies.** Running a workflow or a turn through the Assistant can still consume the flat per-run credit and may pass through the billing gate even when the model itself is BYOK. See [credits & metering](/billing/credits) and [usage gating & limits](/billing/usage-gating).
* **Rate limits and quotas are xAI's.** Token-rate limits, monthly spend caps, and model availability for a BYOK key are governed by your xAI account, not by ModuleX.

<Note>
  BYOK is available on all plans — there is no separate ModuleX entitlement that gates connecting your own xAI key. The pricing matrix on the marketing site lists BYOK for every tier; the only ModuleX-side billing that applies to a BYOK call is the non-model usage described above. **TBD:** confirm with the billing owner that no per-call ModuleX surcharge applies to BYOK model calls before treating "no markup" as a guarantee.
</Note>

## Errors

Catalog and credential operations return ModuleX's standard error shapes. See [errors & status codes](/api-reference/errors) for the full taxonomy.

| Status | When it happens                                                                                                                                    | Shape               |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `400`  | Invalid `auth_data`/`auth_type` on credential create, or asking a typed endpoint for the wrong integration type (for example `xai` is not a tool). | `{detail: string}`  |
| `401`  | Missing or invalid `Authorization` / missing `X-Organization-ID`.                                                                                  | `{detail: string}`  |
| `403`  | Caller is not an owner/admin in the organization.                                                                                                  | `{detail: string}`  |
| `404`  | Unknown provider, for example `GET /integrations/llm-providers/<unknown>` returns `LLM provider not found`.                                        | `{detail: string}`  |
| `422`  | Query/parameter validation error.                                                                                                                  | `{detail: [ ... ]}` |
| `500`  | Unhandled server error.                                                                                                                            | `{detail: string}`  |

<Warning>
  A bad xAI key does not surface as a ModuleX `401`. Connection validation happens against xAI: `POST /credentials/test-temporary` (or saving with validation) returns `is_valid: false` with the status xAI returned (for example `401` from `api.x.ai`). The ModuleX request itself still succeeds.
</Warning>

## Related

<CardGroup cols={2}>
  <Card title="LLM providers" icon="layers" href="/integrations/llm-providers/overview">
    All providers, and how managed vs BYOK selection works.
  </Card>

  <Card title="ModuleX-managed models" icon="gauge" href="/integrations/llm-providers/modulexai">
    The credit-billed managed alternative to BYOK.
  </Card>

  <Card title="Authentication & credentials" icon="lock" href="/integrations/authentication">
    How integrations authenticate and the auth schema variants.
  </Card>

  <Card title="Managing credentials" icon="key-round" href="/integrations/managing-credentials">
    Create, default, rotate, and scope credentials.
  </Card>
</CardGroup>
