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

# Set up in Grok

> Add LedgerSync to Grok, sign in, and ask your first question.

export const AiStuck = () => <div className="lsai-stuck">
    Stuck? <a href="https://ledgersync.com/book-a-demo" target="_blank" rel="noopener noreferrer">Book a call with
    our team</a> and we'll help you, or email{" "}
    <a href="mailto:support@ledgersync.com">support@ledgersync.com</a> with the step and what the screen says.
    Never send passwords or card numbers.
  </div>;

export const AiTest = ({text, stage, children}) => {
  const [copied, setCopied] = useState(false);
  const copy = () => {
    if (navigator.clipboard) {
      navigator.clipboard.writeText(text).then(() => {
        setCopied(true);
        setTimeout(() => setCopied(false), 1600);
      }).catch(() => {});
    }
  };
  return <div className="lsai-test" data-stage={stage}>
      <div className="lsai-test-main">
        <div className="lsai-test-title">Last step: test it in a new chat</div>
        <div className="lsai-test-text">“{text}”</div>
        {children && <div className="lsai-test-more">{children}</div>}
      </div>
      <button type="button" className="lsai-btn lsai-test-button" onClick={copy}>{copied ? "Copied" : "Copy"}</button>
    </div>;
};

export const AiNote = ({tone, children}) => <div className={"lsai-note lsai-note-" + (tone || "gray")}>{children}</div>;

export const AiButton = ({href, children, outline, newTab}) => <a className={outline ? "lsai-btn lsai-btn-outline" : "lsai-btn"} href={href} target={newTab ? "_blank" : undefined} rel={newTab ? "noopener noreferrer" : undefined}>{children}</a>;

export const AiCopy = ({label, text}) => {
  const [copied, setCopied] = useState(false);
  const copy = () => {
    if (navigator.clipboard) {
      navigator.clipboard.writeText(text).then(() => {
        setCopied(true);
        setTimeout(() => setCopied(false), 1600);
      }).catch(() => {});
    }
  };
  return <div className="lsai-copy">
      {label && <div className="lsai-copy-label">{label}</div>}
      <div className="lsai-copy-row">
        <code className="lsai-copy-text">{text}</code>
        <button type="button" className="lsai-copy-button" onClick={copy}>{copied ? "Copied" : "Copy"}</button>
      </div>
    </div>;
};

export const AiStep = ({id, n, total, label, title, img, caption, imgs, stage, children}) => {
  const [open, setOpen] = useState(null);
  const closeRef = useRef(null);
  const openerRef = useRef(null);
  useEffect(() => {
    if (!open) return undefined;
    const root = document.documentElement;
    const overflow = root.style.overflow;
    root.style.overflow = "hidden";
    if (closeRef.current) closeRef.current.focus({
      preventScroll: true
    });
    return () => {
      root.style.overflow = overflow;
      if (openerRef.current) openerRef.current.focus({
        preventScroll: true
      });
    };
  }, [open]);
  const pictures = imgs || (img ? [{
    src: img,
    caption
  }] : []);
  return <div className="lsai-step" id={id} data-stage={stage}>
      <div className="lsai-step-num" aria-hidden="true">{n}</div>
      <div className="lsai-step-main">
        <div className="lsai-step-label">{label || "Step " + n + " of " + total}</div>
        <div className="lsai-step-title">{title}</div>
        <div className="lsai-step-text">{children}</div>
      </div>
      {pictures.length > 0 && <div className="lsai-thumbs">
          {pictures.map(pic => <a key={pic.src} className="lsai-thumb" href={pic.src} title="Click to see it larger" onClick={e => {
    e.preventDefault();
    openerRef.current = e.currentTarget;
    setOpen(pic);
  }}>
              <img src={pic.src} alt="" loading="lazy" />
              <span className="lsai-thumb-caption">{pic.caption ? pic.caption + " · " : ""}click to enlarge</span>
            </a>)}
        </div>}
      {open && <div className="lsai-lightbox" role="dialog" aria-modal="true" aria-label={open.caption || title} onClick={e => {
    if (e.detail < 2) setOpen(null);
  }} onKeyDown={e => {
    if (e.key === "Escape") setOpen(null);
    if (e.key === "Tab") e.preventDefault();
  }}>
          <button ref={closeRef} type="button" className="lsai-lightbox-close" onClick={() => setOpen(null)}>Close</button>
          <img src={open.src} alt={open.caption || title} />
          <span className="lsai-lightbox-note">{open.caption ? open.caption + " · " : ""}Click anywhere to close</span>
        </div>}
    </div>;
};

export const AiPage = ({title, subtitle, video, poster, stage, children}) => {
  const [playing, setPlaying] = useState(false);
  const [current, setCurrent] = useState(stage);
  const pageRef = useRef(null);
  const markRef = useRef(null);
  const topRef = useRef(null);
  const watchRef = useRef(null);
  const closeRef = useRef(null);
  useEffect(() => {
    if (!stage || !topRef.current || !pageRef.current) return undefined;
    const page = pageRef.current;
    const top = topRef.current;
    let frame = 0;
    const update = () => {
      frame = 0;
      const css = getComputedStyle(top);
      const stuck = css.position === "sticky" && markRef.current.getBoundingClientRect().top < (parseFloat(css.top) || 0);
      if (stuck !== top.classList.contains("lsai-top-stuck")) {
        const root = document.documentElement;
        root.style.overflowAnchor = "none";
        requestAnimationFrame(() => requestAnimationFrame(() => {
          root.style.overflowAnchor = "";
        }));
        if (stuck) {
          const before = top.offsetHeight;
          const margin = parseFloat(css.marginBottom) || 0;
          top.style.marginBottom = margin + before + "px";
          top.classList.add("lsai-top-stuck");
          top.style.marginBottom = margin + before - top.offsetHeight + "px";
        } else {
          top.classList.remove("lsai-top-stuck");
          top.style.marginBottom = "";
        }
      }
      const atEnd = window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 8;
      const line = atEnd ? Infinity : top.getBoundingClientRect().bottom + 120;
      if (stuck) {
        const height = top.offsetHeight + "px";
        if (document.documentElement.style.getPropertyValue("--lsai-pinned-h") !== height) {
          document.documentElement.style.setProperty("--lsai-pinned-h", height);
        }
      }
      let next = stage;
      page.querySelectorAll("[data-stage]").forEach(el => {
        if (el.getBoundingClientRect().top < line) next = Number(el.getAttribute("data-stage"));
      });
      setCurrent(next);
    };
    const schedule = () => {
      if (!frame) frame = requestAnimationFrame(update);
    };
    const reset = () => {
      top.classList.remove("lsai-top-stuck");
      top.style.marginBottom = "";
      schedule();
    };
    const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(schedule);
    if (observer) {
      observer.observe(top, {
        box: "border-box"
      });
      observer.observe(page);
    }
    window.addEventListener("scroll", schedule, {
      passive: true
    });
    window.addEventListener("resize", reset);
    update();
    return () => {
      document.documentElement.style.removeProperty("--lsai-pinned-h");
      if (observer) observer.disconnect();
      window.removeEventListener("scroll", schedule);
      window.removeEventListener("resize", reset);
      if (frame) cancelAnimationFrame(frame);
    };
  }, [stage, title]);
  useEffect(() => {
    if (!playing) return undefined;
    const root = document.documentElement;
    const overflow = root.style.overflow;
    root.style.overflow = "hidden";
    if (closeRef.current) closeRef.current.focus({
      preventScroll: true
    });
    return () => {
      root.style.overflow = overflow;
      if (watchRef.current) watchRef.current.focus({
        preventScroll: true
      });
    };
  }, [playing]);
  const stages = ["Get ready", "Add it to your AI", "Sign in", "Click Allow", "Ask a question"];
  return <div ref={pageRef} className={stage ? "lsai-page lsai-page-pinned" : "lsai-page"}>
      <div ref={markRef} className="lsai-top-mark" aria-hidden="true" />
      <div ref={topRef} className="lsai-top">
        <div className="lsai-head">
          <div className="lsai-head-text">
            <h1 className="lsai-title">{title}</h1>
            {subtitle && <p className="lsai-subtitle">{subtitle}</p>}
          </div>
          {video && <button ref={watchRef} type="button" className="lsai-video-button" onClick={() => setPlaying(true)}>
              <span className="lsai-video-play" aria-hidden="true">▶</span>
              <span className="lsai-video-label"><strong>Watch it first</strong><span>Short setup video</span></span>
            </button>}
        </div>
        {stage && <div className="lsai-progress-wrap">
            <ol className="lsai-progress" aria-label="Setup progress">
              {stages.map((label, i) => {
    const n = i + 1;
    const state = n < current ? "lsai-done" : n === current ? "lsai-current" : "lsai-todo";
    return <li key={label} className={"lsai-progress-item " + state} aria-current={n === current ? "step" : undefined}>
                    <span className="lsai-progress-bar" />
                    <span className="lsai-progress-label">{label}</span>
                  </li>;
  })}
            </ol>
            <div className="lsai-progress-now">{stages[current - 1]}</div>
          </div>}
      </div>
      {playing && <div className="lsai-lightbox lsai-video-box" role="dialog" aria-modal="true" aria-label={title + ": setup video"} tabIndex={-1} onClick={e => {
    if (e.target === e.currentTarget) setPlaying(false);
  }} onKeyDown={e => {
    if (e.key === "Escape") setPlaying(false);
    if (e.key === "Tab") {
      e.preventDefault();
      const close = e.currentTarget.querySelector("button");
      (document.activeElement === close ? e.currentTarget.querySelector("video") : close).focus({
        preventScroll: true
      });
    }
  }}>
          <button ref={closeRef} type="button" className="lsai-lightbox-close" onClick={() => setPlaying(false)}>Close</button>
          <video className="lsai-video-player" controls autoPlay playsInline tabIndex={0} poster={poster} src={video} />
          <span className="lsai-lightbox-note">Click Close when you are done</span>
        </div>}
      {children}
    </div>;
};

<AiPage title="Set up in Grok" subtitle="5 steps · about 3 minutes · on grok.com in a web browser" video="/videos/setup-grok.mp4" poster="/videos/setup-grok-poster.jpg" stage={2}>
  <Accordion title="On Grok Business or Enterprise? Open this first">
    Grok's maker, xAI, says your team admin adds LedgerSync for your team once, in the xAI console. Then each
    person connects it with their own LedgerSync login. Not the team admin? Send them this page.

    **The team admin, once. These are xAI's steps:**

    xAI says the admin needs the **Team Read-Write** permission for these steps.

    1. Open [console.x.ai](https://console.x.ai) and pick your team.
    2. Click **Grok Business**, then **Connectors**, then **+ Add Connector**.
    3. Pick **Other**.
    4. Click **Copy** below and paste the LedgerSync address. Then complete any sign-in it asks for.

    <AiCopy label="Your LedgerSync address" text="https://api.ledgersyncappv2.com/mcp" />

    Asked to sign in to LedgerSync? Sign in with your own LedgerSync login and allow it, as in [step 3](#sign-in)
    and step 4 below. Don't create a new LedgerSync account. No LedgerSync login?
    [Book a call with our team](https://ledgersync.com/book-a-demo) and we'll set it up with you.

    **Then each person, with their own LedgerSync login:** xAI says you connect it at
    [grok.com/connectors](https://grok.com/connectors). Sign in and allow it as in [step 3](#sign-in) and step 4
    below. Then do step 5 and the test at the end of this page.
  </Accordion>

  <AiStep id="add" stage={2} n={1} total={5} title="Click New Connector, then Custom" imgs={[{ src: "/images/ai-connector/full/grok-1-new-connector.png", caption: "New Connector circled" }, { src: "/images/ai-connector/full/grok-1-custom.png", caption: "Custom circled" }]}>
    <AiButton href="https://grok.com/connectors" newTab>Open Grok connectors</AiButton>

    Grok opens in a new tab and shows its **Plugins** window, on **Connectors**. Keep it open, and come back to this
    tab for step 2.

    In Grok, click **New Connector** at the top right. Then click **Custom** (it says **Add your own custom
    connector**).

    LedgerSync is already under **Connected**? Go to step 5.
  </AiStep>

  <AiStep id="form" stage={2} n={2} total={5} title="Fill in the form" img="https://mintcdn.com/ledgersync/_45HA8gOrfKXIqo6/images/ai-connector/full/grok-2-form.png?fit=max&auto=format&n=_45HA8gOrfKXIqo6&q=85&s=941281143840cae926786a5ec0c86e77" caption="Name, Server URL and Add Connector circled" width="1280" height="800" data-path="images/ai-connector/full/grok-2-form.png">
    1. In **Name**, type **LedgerSync**.
    2. Click **Copy** below. Click the **Server URL** box (it says `https://mcp.example.com/sse`) and press
       **Ctrl+V** (Windows) or **Command+V** (Mac).
    3. Have your LedgerSync login ready, then click **Add Connector**. A small LedgerSync window opens: sign in
       there right away (step 3).

    <AiCopy label="Your LedgerSync address" text="https://api.ledgersyncappv2.com/mcp" />
  </AiStep>

  <AiStep id="sign-in" stage={3} n={3} total={5} title="Sign in with your LedgerSync login" imgs={[{ src: "/images/ai-connector/full/grok-3-waiting.png", caption: "Grok waits while you sign in" }, { src: "/images/ai-connector/full/ls-1-email.png", caption: "Your email or username, then Next" }, { src: "/images/ai-connector/full/ls-2-password.png", caption: "Sign in circled" }]}>
    Grok says **Complete authentication in the popup window\...** and a small LedgerSync window opens. Sign in there
    right away: Grok waits only a couple of minutes.

    Type the email or username you use in the LedgerSync app. Click **Next**.

    Type your password and click **Sign in**. Asked for a **Two Factor Authentication** code? Type the code from
    your Google Authenticator app and click **Verify**.

    Already signed in to LedgerSync in this browser? The small window goes straight to step 4.

    <AiNote tone="yellow">
      **The page says Create your LedgerSync account?** No LedgerSync login uses that email. Click **Change** and type
      your LedgerSync username. Don't create a second account. Your firm has no LedgerSync account yet? Sign up at
      [ledgersyncappv2.com/sign-up](https://ledgersyncappv2.com/sign-up) first, then come back here.
    </AiNote>

    Nothing opens? Your browser may have blocked the small window. Allow pop-ups for grok.com and try again.

    Grok says **Connection failed**? Click **Go Back** and add it again from step 1. Then sign in right away.
  </AiStep>

  <AiStep id="allow" stage={4} n={4} total={5} title="Click Allow, then Allow access" imgs={[{ src: "/images/ai-connector/full/ls-5-allow.png", caption: "Allow circled" }, { src: "/images/ai-connector/full/grok-4-allow-access.png", caption: "Allow access circled" }]}>
    You see your firm's name. Click **Allow**.

    Then Grok asks to access your account: **Grok would like access to your account**. Scroll down in the small
    window and click **Allow access**. You only see this the first time.

    The small window closes by itself. Grok says **Connector added successfully**.
  </AiStep>

  <AiStep id="connected" stage={4} n={5} total={5} title="Check that LedgerSync is connected" img="https://mintcdn.com/ledgersync/_45HA8gOrfKXIqo6/images/ai-connector/full/grok-5-connected.png?fit=max&auto=format&n=_45HA8gOrfKXIqo6&q=85&s=09aa7015a0372aef6d5f91ed8a1cee10" caption="LedgerSync under Connected and Connector added successfully circled" width="1280" height="800" data-path="images/ai-connector/full/grok-5-connected.png">
    In Grok's **Plugins** window, **LedgerSync** now shows under **Connected**.

    <AiNote tone="yellow">
      **Grok may change things in LedgerSync without asking you first.** In our test, Grok tried to add a client
      without asking. Tell it exactly what you want. Before it sends a message to a client, ask it to show you the
      message first.
    </AiNote>

    Came back later? Open [grok.com/connectors](https://grok.com/connectors). **LedgerSync** shows under **Connected**.
  </AiStep>

  <AiTest text="Use LedgerSync to check whether my account is ready." stage={5}>
    Click **Copy**. In Grok, start a new chat (**Chat** at the top left). Click the message box, press **Ctrl+V**
    (Command+V on a Mac), then press **Enter**.
  </AiTest>

  * Grok says your LedgerSync account is ready: you're done.
  * Grok doesn't use LedgerSync? Click **+** in the message box, then **Connectors**, and turn **LedgerSync** on.
    Then ask again.
  * Anything else: see [Troubleshooting](/ai/troubleshooting).

  <Accordion title="What to ask next">
    <Tip>
      Your clients from the LedgerSync app are already here. Acme is an example: use your client's name.
    </Tip>

    ### Add a client and connect their bank

    <Steps>
      <Step title="Add your client">
        Ask: "Add my client Acme, [acme@example.com](mailto:acme@example.com)."
      </Step>

      <Step title="Connect their bank">
        Ask: "Send Acme a link to connect their bank." Open the link, pick your client's bank on the LedgerSync
        page, and choose what to connect: transactions, statements, checks. Then sign in with their bank login on
        the secure page that opens: LedgerSync's own, or our bank-data partner's for some banks. Some banks need
        one sign-in for each connection. Never in the chat.

        Don't have their bank login? Ask: "Email Acme an invitation to connect their bank." LedgerSync emails them
        a link that signs them in to their LedgerSync account, where they connect the bank themselves. The
        invitation's link works for 6 days, the link above for 3.
      </Step>

      <Step title="Ask about their bank">
        When the bank is connected, ask: "Show Acme's bank balances."
      </Step>
    </Steps>

    ### More things to ask

    <CardGroup cols={2}>
      <Card title="Is a bank supported?" icon="building-columns">
        "Does LedgerSync work with First National Bank?"
      </Card>

      <Card title="Find a client" icon="magnifying-glass">
        "Find my client Acme."
      </Card>

      <Card title="Balances" icon="wallet">
        "Show Acme's bank balances."
      </Card>

      <Card title="Transactions" icon="list">
        "Show last month's transactions for Acme's checking account."
      </Card>

      <Card title="Statements" icon="file-pdf">
        "Get Acme's September bank statement."
      </Card>

      <Card title="Problems" icon="triangle-exclamation">
        "Which of my clients' banks are not working?"
      </Card>

      <Card title="Message clients" icon="envelope">
        "Email every client with a broken American Express connection a link to reconnect it."
      </Card>

      <Card title="Invite a new client to connect their bank" icon="user-plus">
        "Add my new client Acme, [acme@example.com](mailto:acme@example.com), and email them an invitation to connect their bank."
      </Card>

      <Card title="Connect a bank" icon="link">
        "Send Acme a link to connect their bank."
      </Card>

      <Card title="Check images" icon="money-check">
        "Send Acme a link to connect their bank's check images."
      </Card>

      <Card title="Convert a statement PDF" icon="file-arrow-up" href="/ai/convert-statement">
        "Convert a bank statement PDF into transactions."
      </Card>
    </CardGroup>

    Check images arrive in the LedgerSync app, not in the chat. On a check images link, Checks comes already ticked:
    tick Transactions or Statements too to connect them in the same visit.

    <Tip>
      Claude and ChatGPT ask you before they change something. Allow it if it looks right. Grok may change things
      without asking, so tell it exactly what you want.
    </Tip>

    A bank needs the LedgerSync desktop app? The AI tells you when a refresh needs it. See
    [Banks that need the desktop app](/ai/desktop-app).
  </Accordion>

  <AiStuck />
</AiPage>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.