> ## 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.

# Billing, plans & credits — help

> How ModuleX bills: plans, what a credit is, what uses credits, and what happens when you run out. Quick answers for managing cost and usage.

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>;
};

Short answers to the questions people ask most about paying for ModuleX and tracking what they use. For the full detail, follow the link in each answer.

<CardGroup cols={3}>
  <Card title="Plans & pricing" icon="tags" href="/billing/plans">
    Free, Pro, Max, and Enterprise — what each includes.
  </Card>

  <Card title="Credits & metering" icon="coins" href="/billing/credits">
    What a credit is and exactly what consumes credits.
  </Card>

  <Card title="Wallet & top-ups" icon="wallet" href="/billing/wallet">
    The prepaid balance that covers usage beyond your plan.
  </Card>
</CardGroup>

## Billing, plans & credits

<AccordionGroup>
  <Accordion title="How much does ModuleX cost?">
    There is a Free plan, paid Pro and Max plans, and custom Enterprise pricing. Pro is `$25/month` and includes 5,000 credits per month; Max is `$100/month` and includes 20,000 credits per month. See the full breakdown in [Plans & pricing](/billing/plans).
  </Accordion>

  <Accordion title="What is a credit?">
    A credit is how managed usage is measured: `100 credits = $1.00` (one credit is `$0.01`). Running workflows, AI turns, and knowledge searches all draw down credits. See [Credits & metering](/billing/credits).
  </Accordion>

  <Accordion title="What uses credits?">
    Each workflow run or AI turn costs a base credit, plus the cost of any managed AI model usage, knowledge searches, and tool calls. If you bring your own model key (BYOK), that usage is billed by the provider and is not charged in ModuleX credits. See [Credits & metering](/billing/credits).
  </Accordion>

  <Accordion title="What happens when I run out of credits?">
    Managed runs are blocked with a `402` "payment required" response until you have budget again. Top up your [wallet](/billing/wallet), turn on overage, or upgrade your plan in [Plans & pricing](/billing/plans).
  </Accordion>

  <Accordion title="What's the difference between my plan credits and the wallet?">
    Your plan gives a monthly credit allowance. The wallet is a separate prepaid balance that covers usage after the allowance runs out — this is called overage, and you can turn it on for paid plans. See [Wallet & top-ups](/billing/wallet).
  </Accordion>

  <Accordion title="How do I check my usage?">
    Open your dashboard to see credit spend and remaining balance, with per-run detail in your logs. For what each line item means, see [Credits & metering](/billing/credits).

    <MediaEmbed id="MX-MEDIA-4520" type="screenshot" caption={"the usage/analytics view showing credit spend and remaining balance"} />
  </Accordion>

  <Accordion title="Can I get a refund?">
    Contact support to request a refund. Refunds are usually returned as wallet credit rather than to your card. See [Wallet & top-ups](/billing/wallet).
  </Accordion>

  <Accordion title="What's the annual price?">
    Pro and Max can be billed annually. The marketed annual price and the amount charged at checkout do not currently agree, so confirm the exact annual amount on the Stripe checkout screen before you pay. Pricing details are on [Plans & pricing](/billing/plans).
  </Accordion>
</AccordionGroup>

<Note>
  BYOK (bring your own key) usage is never charged in ModuleX credits — it is tracked for analytics only and billed directly by the upstream provider.
</Note>

## Keep reading

<CardGroup cols={2}>
  <Card title="Errors & troubleshooting" icon="circle-question" href="/help/errors-troubleshooting">
    What a `402`, `403`, or `429` means and how to clear it.
  </Card>

  <Card title="Usage gating & limits" icon="shield-halved" href="/billing/usage-gating">
    The admission gate and the responses it returns when limits are hit.
  </Card>
</CardGroup>
