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

# Rendering Guides

> Fetch a connector's guides from the API and render them in your own product.

Guides live in the connector YAML under `support.guides`, so they ship and version with the connector instead of going stale in a separate docs site while the connector changes. Fetch them from the API to render in your own product.

<Card title="support and Guides" icon="file-code" href="/connector-yaml-reference/yaml-schema#support-and-guides">
  The schema: sections, steps, warnings, images, and scope filtering.
</Card>

## Fetch the guides

Guides come back from `GET /actions` when you ask for them:

```bash theme={null}
curl -X GET "https://api.stackone.com/actions?include=authentication_guides&filter[connectors]=[provider]" \
  -H "Authorization: Basic $(echo -n 'YOUR_API_KEY:' | base64)"
```

| Parameter                       | Description                                                          |
| ------------------------------- | -------------------------------------------------------------------- |
| `include=authentication_guides` | Returns `support.guides` for each authentication method              |
| `include=event_guides`          | Returns the event guides from `events.guides`                        |
| `include=action_details`        | Returns extended action metadata                                     |
| `filter[connectors]`            | Restrict to one connector key, such as `filter[connectors]=bamboohr` |
| `page_size`                     | Results per page                                                     |
| `next`                          | Pagination cursor from the previous response                         |

<Card title="GET /actions" icon="code" href="/platform/api-reference/actions/list-all-connectors-actions-metadata">
  Full parameter and response reference.
</Card>

## Response shape

Guides are nested per authentication method, since each method needs different instructions:

```json theme={null}
{
  "data": [
    {
      "key": "your_provider",
      "name": "Your Provider",
      "authentication": [
        {
          "type": "custom",
          "label": "API Key",
          "key": "api_key",
          "configFields": [
            { "key": "apiKey", "label": "API Key", "type": "password", "required": true }
          ],
          "support": {
            "guides": {
              "config": {
                "warning": "Admin access required to generate an API key.",
                "sections": [
                  {
                    "title": "Generating an API Key",
                    "content": "Generate an API key from your admin dashboard.",
                    "steps": [
                      {
                        "title": "Sign in and open API settings",
                        "content": "Sign in to your Provider account.",
                        "list": [
                          "Click **Settings** in the top navigation",
                          "Select **API** from the sidebar",
                          "Click **Create API Key**"
                        ]
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      ],
      "actions": [
        {
          "id": "your_provider_list_employees",
          "label": "List Employees",
          "required_scopes": ["employees:read"]
        }
      ]
    }
  ],
  "next": null
}
```

## Render in your own UI

<Steps>
  <Step title="Fetch and parse">
    The shape is small enough to type by hand. `title` and `content` are always present; everything else is optional:

    ```typescript theme={null}
    interface GuideImage {
      src: string;
      alt: string;
    }

    interface GuideStep {
      title: string;
      content: string;
      list?: string[];
      image?: GuideImage;
      /** Space-separated scope names, not an array */
      applicableScopes?: string;
      /** Render badges for the actions these scopes unlock */
      displayScopes?: boolean;
    }

    interface GuideSection {
      title: string;
      content: string;
      list?: string[];
      image?: GuideImage;
      steps?: GuideStep[];
      applicableScopes?: string;
    }

    interface AuthGuides {
      config?: { warning?: string; sections: GuideSection[] };
      setup?: { warning?: string; sections: GuideSection[] };
    }

    async function fetchConnectorGuides(
      connectorKey: string,
      apiKey: string,
      authMethodKey?: string,
    ): Promise<AuthGuides> {
      const authHeader = Buffer.from(`${apiKey}:`).toString("base64");

      const response = await fetch(
        `https://api.stackone.com/actions?include=authentication_guides&filter[connectors]=${connectorKey}`,
        { headers: { Authorization: `Basic ${authHeader}` } },
      );

      const { data } = await response.json();
      const connector = data?.find((c: any) => c.key === connectorKey);

      if (!connector) {
        throw new Error(`Connector "${connectorKey}" not found`);
      }

      const auth = authMethodKey
        ? connector.authentication?.find((a: any) => a.key === authMethodKey)
        : connector.authentication?.[0];

      return auth?.support?.guides ?? {};
    }
    ```

    In the browser, swap `Buffer.from(...)` for `btoa(`\${apiKey}:`)`.
  </Step>

  <Step title="Render content">
    <Warning>
      `content` and `list` items contain markdown: links, bold for UI labels, backticks for URLs and values. Render them through a markdown component such as `react-markdown` and sanitize the output. Building HTML strings by hand and injecting them with `dangerouslySetInnerHTML` puts provider-authored text straight into your DOM.
    </Warning>

    ```tsx theme={null}
    import ReactMarkdown from "react-markdown";

    function Section({ section }: { section: GuideSection }) {
      return (
        <section>
          <h3>{section.title}</h3>
          <ReactMarkdown>{section.content}</ReactMarkdown>

          {section.list && (
            <ul>
              {section.list.map((item) => (
                <li key={item}>
                  <ReactMarkdown>{item}</ReactMarkdown>
                </li>
              ))}
            </ul>
          )}

          {section.image && <img src={section.image.src} alt={section.image.alt} />}

          {section.steps?.map((step) => (
            <div key={step.title}>
              <h4>{step.title}</h4>
              <ReactMarkdown>{step.content}</ReactMarkdown>
            </div>
          ))}
        </section>
      );
    }
    ```
  </Step>

  <Step title="Filter by scope">
    `applicableScopes` marks a section or step as relevant only to certain scopes, so a read-only integration isn't told to grant write access. It's a **space-separated string**, so split it before comparing:

    ```typescript theme={null}
    function appliesTo(scopes: string | undefined, selected: string[]): boolean {
      if (!scopes) {
        return true;
      }
      return scopes.split(/\s+/).some((scope) => selected.includes(scope));
    }

    const visible = sections.filter((section) => appliesTo(section.applicableScopes, selected));
    ```

    A section with no `applicableScopes` always shows. Steps carry the same field, so filter them the same way.
  </Step>
</Steps>

## Related

<Card title="YAML Schema" icon="file-code" href="/connector-yaml-reference/yaml-schema#support-and-guides">
  The guide, section, and step fields in full.
</Card>
