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

# Connector Documentation

> Add setup guides to your connector configuration that users can access programmatically

When you build a custom connector, you can embed step-by-step setup guides directly in the connector YAML configuration. These guides are exposed through the StackOne API's `/actions` endpoint and can be rendered in your own documentation, dashboards, or integration hubs.

***

## Overview

Connector documentation consists of two types of guides:

<CardGroup cols={2}>
  <Card title="Account Link Guides" icon="link">
    **For end-users** - Instructions to connect their account via Integration Hub. Covers finding credentials like API keys, domains, and OAuth authorization.
  </Card>

  <Card title="Auth Setup Guides" icon="key">
    **For application setup** - Instructions to register OAuth applications and obtain client credentials before users can connect.
  </Card>
</CardGroup>

**Where guides go:**

* Account link guides → `authentication[].{method}.support.guides.config`
* Auth setup guides → `authentication[].{method}.support.guides.setup`

***

## Guide Structure in YAML

Guides are added to the `authentication` block in your connector YAML configuration.

### Basic Example

```yaml theme={null}
authentication:
  - custom:
      type: custom
      label: API Key
      support:
        guides:
          config:                          # Account linking guide (for end-users/resource owners)
            warning: "Admin access required to generate an API key."
            sections:
              - title: Generating an API Key
                content: |
                  Instructions for finding the API key.
                steps:
                  - title: Navigate to Settings
                    content: |
                      Go to Settings > API in your account.
                  - title: Create Key
                    content: |
                      Click Generate API Key and copy it.
      authorization:
        type: bearer
        token: $.credentials.apiKey
      configFields:
        - key: apiKey
          label: API Key
          type: password
          required: true
          secret: true
```

### When to Use Each Guide Type

| Guide Type      | Field Dependency        | Purpose                                                  | Audience                    |
| --------------- | ----------------------- | -------------------------------------------------------- | --------------------------- |
| `guides.config` | Requires `configFields` | How end-users get their credentials                      | End-users (resource owners) |
| `guides.setup`  | Requires `setupFields`  | How to register OAuth apps and obtain client credentials | Application owners          |

<Warning>
  Only include `guides.config` if `configFields` exists. Only include `guides.setup` if `setupFields` exists.
</Warning>

### The support.link Field

<Warning>
  **Critical:** Set `support.link` to the URL where you'll render these guides in your own documentation or dashboard. The Integration Hub uses this link to direct users to your rendered guides. If not set, the Hub will link to StackOne's generic documentation instead of your custom instructions.
</Warning>

```yaml theme={null}
authentication:
  - custom:
      type: custom
      label: API Key
      support:
        link: https://docs.yourcompany.com/integrations/provider-setup  # Required
        description: Admin privileges required
        guides:
          config:
            # ... your guide content
```

The `support.link` should point to where you host the rendered version of these guides, ensuring users see your branded, customized setup instructions.

***

## Section Structure

Each guide contains an array of sections with steps.

### Section Properties

```yaml theme={null}
sections:
  - title: Section Title                   # Required
    content: |                             # Optional - Intro text
      Section overview text.
    list:                                  # Optional - Bullet points
      - Item 1
      - Item 2
    steps:                                 # Optional - Nested steps
      - title: Step Title
        content: |
          Step instructions.
        list:
          - Sub-item 1
          - Sub-item 2
    applicableScopes: employees:read       # Optional - Filter by scopes (space-separated)
```

### Content Formatting

The `content` and `list` fields contain plain strings. To render markdown formatting, use a markdown parser in your rendering code. Common patterns include:

* **Links:** `[Provider Dashboard](https://example.com/dashboard)` → Parse with markdown renderer to create clickable links
* **Bold:** `**Settings**` for UI elements → Parse to render as `<strong>Settings</strong>`
* **Code:** `` `https://api.example.com` `` → Parse to render as `<code>https://api.example.com</code>`

<Tip>
  The API returns raw strings with markdown syntax. You're responsible for parsing and rendering them. Use libraries like `react-markdown`, `marked`, or similar, and always sanitize HTML output with tools like `DOMPurify` to prevent XSS attacks.
</Tip>

***

## Scope Definitions

<Warning>
  **Preview Feature:** Scope definitions and scope-aware guides are under active development. The structure and behavior may change. Currently used primarily for OAuth scopes, but designed to support any action requirements (pricing tiers, platform configuration, feature flags, etc.).
</Warning>

Define action requirements in `scopeDefinitions` at the connector root level. While commonly used for OAuth/API scopes, these can represent any prerequisite needed to enable an action.

### Basic Scopes

```yaml theme={null}
scopeDefinitions:
  employees:read:
    description: Read employee data
  employees:write:
    description: Create and update employee records
    includes: employees:read              # Write includes read
```

<Tip>
  Scopes aren't limited to API permissions. Use them to represent pricing tiers (`plan:enterprise`), platform features (`feature:advanced_reporting`), or configuration requirements (`config:sso_enabled`).
</Tip>

### Hierarchical Scopes

```yaml theme={null}
scopeDefinitions:
  https://www.googleapis.com/auth/drive:
    description: View and manage all Drive files
    includes: https://www.googleapis.com/auth/drive.readonly
  https://www.googleapis.com/auth/drive.readonly:
    description: View all Drive files (read-only)
```

**Rules:**

* Write scopes typically include read scopes via `includes`
* Broader scopes include narrower scopes
* Only include relationships explicitly documented by provider
* Read-only scopes should NOT include write scopes

***

## Scope-Aware Guide Content

Guide sections can be filtered based on selected scopes or requirements, showing only relevant instructions for the user's configuration.

### Basic Scope Filtering

```yaml theme={null}
guides:
  config:
    sections:
      - title: Read Permissions
        applicableScopes: employees:read   # Only show this section when this scope selected
        steps:
          - title: Enable Read Access
            content: |
              Grant read permissions in the admin panel.

      - title: Write Permissions
        applicableScopes: employees:write  # Only show this section when this scope selected
        steps:
          - title: Enable Write Access
            content: |
              Grant write permissions for creating/updating employees.
```

### Displaying Actions Enabled by Requirements

Use `displayScopes: true` to show which actions a step enables:

```yaml theme={null}
steps:
  - title: Select API Scopes
    content: |
      Choose the scopes you need based on your use case.
    displayScopes: true
    applicableScopes: employees:read employees:write departments:read  # Space-separated list
```

When rendered, this shows badges indicating which actions are enabled by these requirements (scopes, features, etc.).

***

## Complete Examples

### API Key Authentication

```yaml theme={null}
authentication:
  - custom:
      type: custom
      label: API Key
      support:
        description: Admin privileges required
        guides:
          config:
            warning: "Admin access to your account is 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](https://app.provider.com/signin).
                    list:
                      - Click **Settings** in the top navigation
                      - Select **API** from the sidebar
                      - Click **Create API Key**
                  - title: Name and create the key
                    content: |
                      Give your API key a descriptive name.
                    list:
                      - "**Name:** Enter 'StackOne Integration'"
                      - Click **Generate Key**
                  - title: Copy the API key
                    content: |
                      Copy your new API Key and store it securely.
                    list:
                      - This key will only be shown once
                      - Save it in a secure password manager
      authorization:
        type: bearer
        token: $.credentials.apiKey
      configFields:
        - key: apiKey
          label: API Key
          type: password
          required: true
          secret: true
          placeholder: sk_live_abc123def456
          description: Generate via Settings > API in your Provider account
      environments:
        - key: production
          name: Production
```

### OAuth 2.0 with Setup Guide

```yaml theme={null}
authentication:
  - oauth2:
      type: oauth2
      label: OAuth 2.0
      support:
        description: OAuth application setup required
        guides:
          setup:                           # For application owners - registering OAuth client
            warning: "Admin access required to create OAuth applications."
            sections:
              - title: Create OAuth Application
                content: |
                  Register an OAuth application in your Provider dashboard.
                steps:
                  - title: Navigate to OAuth Apps
                    content: |
                      Go to Settings > Developer > OAuth Applications.
                  - title: Register New Application
                    content: |
                      Click **New OAuth App** and configure:
                    list:
                      - "**Application Name:** StackOne"
                      - "**Redirect URI:** `https://api.stackone.com/connect/oauth2/provider_key/callback`"
                  - title: Copy Credentials
                    content: |
                      Save your Client ID and Client Secret.
                    list:
                      - Copy the Client ID immediately
                      - Generate and copy the Client Secret
                      - Store both securely for use later
          config:                          # For end-users/resource owners - authorizing access
            sections:
              - title: OAuth Connection Flow
                content: |
                  Authorize StackOne to access your account.
                steps:
                  - title: Initiate Connection
                    content: |
                      Click **Connect** in the StackOne Hub.
                  - title: Review Permissions
                    content: |
                      Review the requested permissions.
                    displayScopes: true
                    applicableScopes: employees:read employees:write  # Space-separated list
                  - title: Authorize Access
                    content: |
                      Click **Authorize** to grant access.
      authorization:
        type: oauth2
        authorizationUrl: https://provider.com/oauth/authorize
        tokenUrl: https://provider.com/oauth/token
        tokenRequest:
        args:
          - name: client_id
            value: $.credentials.clientId
            in: body
          - name: client_secret
            value: $.credentials.clientSecret
            in: body
          - name: code
            value: $.credentials.code
            in: body
          - name: grant_type
            value: authorization_code
            in: body
      setupFields:
        - key: clientId
          label: Client ID
          type: text
          required: true
        - key: clientSecret
          label: Client Secret
          type: password
          required: true
          secret: true

scopeDefinitions:
  employees:read:
    description: Read employee data
  employees:write:
    description: Create and update employee records
    includes: employees:read
```

***

## Retrieving Guides via API

Once your connector is deployed, guides are available through the `/actions` API endpoint.

### API Request

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

### Response Structure

```json theme={null}
{
  "data": [
    {
      "key": "your_provider",
      "name": "Your Provider",
      "icon": "https://stackone-logos.com/api/your_provider/filled/png",
      "authentication": [
        {
          "type": "custom",
          "label": "API Key",
          "key": "api_key",
          "configFields": [
            {
              "key": "apiKey",
              "label": "API Key",
              "type": "password",
              "required": true,
              "secret": true,
              "placeholder": "sk_live_abc123"
            }
          ],
          "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
}
```

### Query Parameters

| Parameter            | Description                          | Example                         |
| -------------------- | ------------------------------------ | ------------------------------- |
| `include`            | Must include `authentication_guides` | `include=authentication_guides` |
| `filter[connectors]` | Filter by connector key              | `filter[connectors]=bamboohr`   |
| `page_size`          | Results per page                     | `page_size=100`                 |
| `next`               | Pagination cursor                    | `next=cursor_string`            |

***

## Rendering Guides in Your System

You can render the guides however you choose. Here's a basic approach using TypeScript and React:

### 1. Fetch and Parse

```typescript theme={null}
interface GuideSection {
  title: string;  // Required per YAML schema
  content?: string;
  list?: string[];
  steps?: GuideStep[];
  applicableScopes?: string[];
}

interface GuideStep {
  title: string;  // Required per YAML schema
  content?: string;
  list?: string[];
  displayScopes?: boolean;  // Whether to show requirement badges for this step
  applicableScopes?: string[];  // Filter step by requirements (OAuth scopes, features, etc.)
}

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

async function fetchConnectorGuides(
  connectorKey: string,
  apiKey: string,
  authMethodKey?: string
): Promise<AuthGuides> {
  // Browser: btoa(apiKey + ':')
  // Node.js: Buffer.from(apiKey + ':').toString('base64')
  const authHeader = typeof btoa !== 'undefined'
    ? btoa(apiKey + ':')
    : 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();

  // Normalize connectors list from API response (supports both documented and legacy shapes)
  const connectors = Array.isArray(data?.data)
    ? data.data
    : Array.isArray(data?.results)
    ? data.results
    : [];

  // Find the connector by key
  const connector = connectors.find(
    (c: any) => c.key === connectorKey || c.connector_key === connectorKey
  );

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

  // Find the auth method by key, or use the first one
  const auth = authMethodKey
    ? connector.authentication?.find((a: any) => a.key === authMethodKey)
    : connector.authentication?.[0];

  if (!auth) {
    throw new Error(`Auth method not found`);
  }

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

### 2. Render Content

<Warning>
  Use a proper Markdown parser (like `react-markdown` or `marked`) with HTML sanitization (like `DOMPurify`) instead of regex replacements. The example below is simplified for demonstration and should not be used in production without proper sanitization.
</Warning>

```typescript theme={null}
// PRODUCTION: Use react-markdown + DOMPurify for safe rendering
// Example: import ReactMarkdown from 'react-markdown'
// Example: import DOMPurify from 'dompurify'

function renderGuideContent(content: string): string {
  // SIMPLIFIED EXAMPLE - Add HTML sanitization for production use
  const escapeHtml = (text: string) =>
    text.replace(/[&<>"']/g, (m) => ({
      '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#039;'
    }[m] || m));

  return content
    .replace(/\*\*(.*?)\*\*/g, (_, text) => `<strong>${escapeHtml(text)}</strong>`)
    .replace(/`(.*?)`/g, (_, text) => `<code>${escapeHtml(text)}</code>`)
    .replace(/\[(.*?)\]\((.*?)\)/g, (_, text, url) =>
      `<a href="${escapeHtml(url)}">${escapeHtml(text)}</a>`
    );
}

function renderSection(section: GuideSection): JSX.Element {
  return (
    <div className="guide-section">
      {section.title && <h3>{section.title}</h3>}
      {section.content && (
        <div dangerouslySetInnerHTML={{ __html: renderGuideContent(section.content) }} />
      )}
      {section.list && (
        <ul>
          {section.list.map((item, i) => (
            <li key={i} dangerouslySetInnerHTML={{ __html: renderGuideContent(item) }} />
          ))}
        </ul>
      )}
      {section.steps && section.steps.map((step, i) => (
        <div key={i} className="guide-step">
          {step.title && <h4>{step.title}</h4>}
          {step.content && (
            <div dangerouslySetInnerHTML={{ __html: renderGuideContent(step.content) }} />
          )}
          {step.list && (
            <ul>
              {step.list.map((item, j) => (
                <li key={j} dangerouslySetInnerHTML={{ __html: renderGuideContent(item) }} />
              ))}
            </ul>
          )}
        </div>
      ))}
    </div>
  );
}
```

### 3. Handle Requirement Filtering

```typescript theme={null}
function filterByRequirements(
  sections: GuideSection[],
  selectedRequirements: string[]
): GuideSection[] {
  return sections.filter(section => {
    if (!section.applicableScopes) return true;
    // Show section if any of its requirements are met
    return section.applicableScopes.some(req => selectedRequirements.includes(req));
  });
}
```

***

## Validation

After adding guides to your connector YAML, validate the configuration:

```bash theme={null}
stackone validate connectors/your-provider/your-provider.connector.s1.yaml
```

<Note>
  If you see a warning about `Unknown field 'guides'`, update your CLI to the latest version with `npm install -g @stackone/cli@latest`. The guides field is fully supported at runtime.
</Note>

***

## Testing Your Guides

### 1. Deploy Connector

```bash theme={null}
stackone push connectors/your-provider/ --api-key YOUR_API_KEY
```

### 2. Fetch from API

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

### 3. Verify Response

Check that:

* [ ] `authentication[].support.guides.config` exists if `configFields` exist
* [ ] `authentication[].support.guides.setup` exists if `setupFields` exist
* [ ] All sections have `title` and `content` or `steps`
* [ ] Links are properly formatted
* [ ] Requirement filters (`applicableScopes`) match your `scopeDefinitions` if used

***

## Migration from Hub Docs

If you have existing guides in separate documentation, you can migrate them to the connector YAML.

### MDX to YAML Mapping

| MDX Element          | YAML Equivalent           |
| -------------------- | ------------------------- |
| `<Warning>` at top   | `warning:` field          |
| `## Section Title`   | `- title: Section Title`  |
| `<Steps>` block      | `steps:` array            |
| `<Step title="...">` | `- title:` in steps       |
| Paragraph content    | `content: \|` (multiline) |
| Bulleted list        | `list:` array             |
| `<Frame><img>`       | Omit (images not in YAML) |
| Links `[text](url)`  | Keep as-is                |

### Example Migration

**From MDX:**

```mdx theme={null}
<Warning>
  Admin privileges required.
</Warning>

## Finding Your API Key

<Steps>
  <Step title="Open Settings">
    Navigate to Settings > API Keys.
    - Click **Generate Key**
    - Copy the key immediately
  </Step>
</Steps>
```

**To YAML:**

```yaml theme={null}
guides:
  config:
    warning: "Admin privileges required."
    sections:
      - title: Finding Your API Key
        content: |
          Generate your API key from the admin dashboard.
        steps:
          - title: Open Settings
            content: |
              Navigate to Settings > API Keys.
            list:
              - Click **Generate Key**
              - Copy the key immediately
```

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Build Your Connector" icon="wrench" href="/guides/connector-engine/building-first-connector">
    Create the connector YAML configuration
  </Card>

  <Card title="Connector Structure" icon="book" href="/guides/connector-engine/connector-structure">
    Learn about authentication patterns and actions
  </Card>

  <Card title="YAML Reference" icon="file-code" href="/guides/connector-engine/connector-yaml-reference">
    Complete reference for all YAML properties
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/guides/connector-engine/cli-reference">
    Deploy and test connectors with the CLI
  </Card>
</CardGroup>
