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

# Credentials & integrations — help

> Quick answers for connecting external services to ModuleX: add an OAuth or API-key credential, browse the 175 integrations, find a tool, bring your own keys (BYOK), how credentials are encrypted, fix a broken OAuth connection, and build your own integration.

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 connecting ModuleX to the services you already use, so your workflows and the Assistant can act on your behalf. For the full detail, follow the link in each answer.

<CardGroup cols={2}>
  <Card title="Integrations overview" icon="plug" href="/integrations/overview">
    Connect ModuleX to 175 services and call their tools from workflows and the Assistant.
  </Card>

  <Card title="Authentication & credentials" icon="key" href="/integrations/authentication">
    How integrations authenticate: OAuth2, API keys, bearer tokens, and managed keys.
  </Card>

  <Card title="Integration catalog" icon="grid" href="/integrations/catalog">
    Browse the full catalog of 175 integrations by category.
  </Card>

  <Card title="Managing credentials" icon="rotate" href="/integrations/managing-credentials">
    Create, set a default, test, and remove credentials in the app or via the API.
  </Card>
</CardGroup>

## Credentials & integrations

<AccordionGroup>
  <Accordion title="How do I connect an integration?">
    Add a credential for the service you want to use. For an OAuth integration you click connect and approve access on the provider's site (for example GitHub); for a key-based integration you paste an API key or token. Adding and managing credentials needs an owner or admin role on the organization. See [Authentication & credentials](/integrations/authentication) for each connection type.

    <MediaEmbed id="MX-MEDIA-4560" type="screenshot" caption={"connecting an OAuth integration (GitHub) from the credentials screen in the ModuleX app"} />
  </Accordion>

  <Accordion title="How many integrations are there?">
    There are 175 integrations available today, spanning developer tools, communication, CRM, data, and more. Browse them all in the [integration catalog](/integrations/catalog), or read the [integrations overview](/integrations/overview) for what they can do.
  </Accordion>

  <Accordion title="Why can't I find a tool I want?">
    A tool usually only becomes available once you have connected its integration. Add a credential for that service and its actions appear for use in workflows and the Assistant. See [Managing credentials](/integrations/managing-credentials).
  </Accordion>

  <Accordion title="Can I use my own API keys (BYOK)?">
    Yes. With bring-your-own-key (BYOK) you supply your own credential for a provider, and that usage is billed by the provider directly — it is not charged in ModuleX credits. ModuleX-managed keys are the alternative and are metered in credits. See [Authentication & credentials](/integrations/authentication) and [Credits & metering](/billing/credits).
  </Accordion>

  <Accordion title="Where are my credentials stored?">
    Credentials are encrypted at rest with a key scoped to your organization and the specific credential, so they cannot be reused outside it. Secrets are decrypted only when a tool runs, and the API returns masked values (for example `start***end`) rather than the raw secret. See [Data security & encryption](/security/data-encryption) and [Credentials & OAuth2](/concepts/credentials-oauth).
  </Accordion>

  <Accordion title="How do I fix an expired OAuth connection?">
    For most providers, OAuth tokens refresh automatically just before they expire, so you do not need to do anything. If a connection breaks, reconnect the credential — remove it and connect the service again. The manual "refresh" action in the app is a [known limitation](/help/known-limitations) and may not work, so prefer reconnecting. See [Managing credentials](/integrations/managing-credentials).
  </Accordion>

  <Accordion title="Can I build my own integration?">
    Yes, but not from inside the app yet. You add a custom integration by packaging it as code (a tool package the runtime discovers) or by connecting a [custom MCP server](/integrations/building/custom-mcp). See [Build an integration](/integrations/building/overview) to get started.
  </Accordion>
</AccordionGroup>

<Note>
  Connecting, testing, and removing credentials all require an owner or admin role on the organization. If a teammate cannot add or see a credential, check their role under [Account & access](/help/account-access).
</Note>

## Related help

<CardGroup cols={3}>
  <Card title="Knowledge (RAG)" icon="book-open" href="/help/knowledge-rag">
    Connect a provider key for BYOK embeddings or an external vector store.
  </Card>

  <Card title="Known limitations" icon="triangle-exclamation" href="/help/known-limitations">
    The OAuth refresh button and other things to be aware of.
  </Card>

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