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

# Basin

> Connect Basin to read form submissions and manage your forms from chat.

export const TryPromptButton = ({prompt, imageSrc, imageAlt = "Template preview", imageStyles = {}, buttonCta = "Build in Replo"}) => {
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  const APP_URL = "https://dashboard.replo.app";
  const LoaderIcon = <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{
    animation: "spin 1s linear infinite"
  }}>
      <path d="M21 12a9 9 0 1 1-6.219-8.56" />
    </svg>;
  const ChevronIcon = <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="m9 18 6-6-6-6" />
    </svg>;
  async function postJSON(url, body, headers = {}, timeoutMs = 120000) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
    try {
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...headers
        },
        body: JSON.stringify(body ?? ({})),
        signal: controller.signal
      });
      const responseText = await response.text();
      if (!response.ok) throw new Error(`API Error: ${response.status}`);
      return responseText ? JSON.parse(responseText) : {};
    } finally {
      clearTimeout(timeoutId);
    }
  }
  async function handleTryPrompt(event) {
    event.preventDefault();
    event.stopPropagation();
    setIsLoading(true);
    setError(null);
    try {
      const body = {
        prompt,
        file: null
      };
      const {seed} = await postJSON(`${PUBLISHER_API_BASE_URL}/api/v1/marketing/issue-marketing-site-jwt`, body);
      if (!seed) throw new Error("No seed returned from API");
      const url = new URL(APP_URL);
      url.searchParams.set("type", "agent");
      url.hash = `seed=${encodeURIComponent(seed)}`;
      window.open(url.toString(), "_blank");
      setIsLoading(false);
    } catch (caughtError) {
      console.error("Failed to generate prompt:", caughtError);
      const message = caughtError instanceof Error ? caughtError.message : null;
      setError(message ?? "Something went wrong. Please try again.");
      setIsLoading(false);
    }
  }
  return <div style={{
    position: "relative",
    display: "inline-block",
    width: "100%"
  }}>
      {}
      {imageSrc && <img src={imageSrc} alt={imageAlt} style={{
    width: "100%",
    height: "auto",
    display: "block",
    borderRadius: "8px",
    opacity: 0.8,
    ...imageStyles
  }} />}

      {}
      <div style={imageSrc ? {
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    zIndex: 10
  } : {
    display: "flex",
    justifyContent: "flex-start",
    margin: "1.25rem 0"
  }}>
        <button type="button" className="try-replo-btn" onClick={handleTryPrompt} disabled={isLoading} style={{
    backgroundColor: "#274AE2",
    color: "#ffffff",
    padding: "0.5rem 1.1rem",
    fontSize: "0.875rem",
    fontWeight: 600,
    fontFamily: "inherit",
    border: "none",
    borderRadius: "9999px",
    cursor: isLoading ? "not-allowed" : "pointer",
    lineHeight: 1.4,
    whiteSpace: "nowrap",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    WebkitFontSmoothing: "antialiased",
    boxSizing: "border-box",
    opacity: isLoading ? 0.7 : 1,
    boxShadow: "0 1px 2px rgba(15, 23, 42, 0.08)",
    transition: "background-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease"
  }}>
          <span style={{
    visibility: isLoading ? "hidden" : "visible",
    display: "inline-flex",
    alignItems: "center",
    gap: "0.375rem"
  }}>
            {buttonCta}
            {ChevronIcon}
          </span>
          {isLoading && <span style={{
    position: "absolute",
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center"
  }}>
              {LoaderIcon}
            </span>}
        </button>
      </div>

      {}
      <style>
        {`
          @keyframes spin {
            from {
              transform: rotate(0deg);
            }
            to {
              transform: rotate(360deg);
            }
          }
          .try-replo-btn:hover:not(:disabled) {
            background-color: #1f3ec0 !important;
            box-shadow: 0 4px 12px rgba(39, 74, 226, 0.35);
            transform: translateY(-1px);
          }
          .try-replo-btn:active:not(:disabled) {
            transform: translateY(0);
            box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
          }
          .try-replo-btn:focus-visible {
            outline: 2px solid #274AE2;
            outline-offset: 2px;
          }
        `}
      </style>

      {}
      {error && <div style={{
    marginTop: "12px",
    padding: "12px 16px",
    backgroundColor: "#fee",
    border: "1px solid #fcc",
    borderRadius: "6px",
    color: "#c33",
    fontSize: "14px",
    textAlign: "center"
  }} role="alert">
          {error}
        </div>}
    </div>;
};

[Basin](https://usebasin.com) is a no-code form backend: your site's forms post submissions to Basin, and Basin stores them. Connect Basin so Replo can pull those submissions into chat, read and manage your forms, and organize your projects.

## Connect Basin

Basin connects with an account API key that you paste into Replo.

<Steps>
  <Step title="Open the Integrations app">
    In Replo, open the [Integrations app](/apps/integrations) and find
    **Basin**.
  </Step>

  <Step title="Paste your API key">
    In the connection block, paste your Basin **Account API key** and click
    **Connect**. The link above the field takes you straight to your Basin API
    key page.
  </Step>
</Steps>

You can also connect straight from chat; if you ask Replo to use Basin before it's connected, it drops the connection card right into the conversation.

```text theme={null}
Connect my Basin account
```

<TryPromptButton prompt="Connect my Basin account" />

### Finding your API key

Use an **Account API key**, which covers all of your forms, projects, and domains. A form-scoped key only reaches a single form and won't work with the forms, projects, and domains tools.

1. Log in to [Basin](https://usebasin.com).
2. Open [**Account Settings → API Settings**](https://usebasin.com/app/api_settings).
3. Copy your **Account API key** and paste it into Replo.

For more detail, see Basin's [API access guide](https://docs.usebasin.com/account-management/api-access/).

<Note>API access requires a Basin Growth, Pro, or Agency plan.</Note>

## What you can do

Once connected, ask Replo about your forms and submissions. Point it at Basin with an [@-mention](/sessions-and-history#mentions).

```text theme={null}
Show me my latest Basin form submissions
```

<TryPromptButton prompt="Show me my latest Basin form submissions" />

Replo can list and read submissions, create and update forms, and organize projects. It confirms with you before it creates or changes anything, and it can't delete your forms or submissions.
