# Mintlify Integration (GitHub)

[Mintlify](https://mintlify.com/) is a documentation platform that generates beautiful docs sites from Markdown and MDX files stored in a GitHub repository. Every push to the tracked branch triggers an automatic redeploy of the docs site.

LaunchBrightly integrates with Mintlify by connecting directly to the underlying GitHub repository via a GitHub App. This allows LaunchBrightly to import articles from your docs repo and sync updated screenshots by opening pull requests with replacement images.

💡 How it differs from other Help Center integrations

Zendesk, Intercom and other help center integrations update articles via each platform's REST API. Mintlify integrations work through Git: LaunchBrightly reads your MDX/MD files from the repo, matches screenshots by metadata or hash and commits replacement images to a new branch. A pull request is opened (and optionally auto-merged) so the change flows through your normal review process.

## Prerequisites

Before creating a Mintlify integration, you need:

1. A GitHub repository containing your Mintlify docs (MDX or Markdown files).
2. A LaunchBrightly API key. See [Getting Started](https://docs.launchbrightly.com/getting-started.html).

---

## Create a Mintlify integration

`POST /integration`

### Request

```json
{
  "label": "Acme Docs (Mintlify)",
  "provider": "mintlify",
  "platform": "github",
  "credentials": {
    "installationId": "12345678",
    "owner": "your-org",
    "repo": "your-docs-repo",
    "branch": "main",
    "docs": "docs",
    "siteUrl": "https://docs.your-domain.com"
  }
}
```

##### cURL

```bash
curl --location --request POST 'https://api.launchbrightly.com/integration' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
  "label": "Acme Docs (Mintlify)",
  "provider": "mintlify",
  "platform": "github",
  "credentials": {
    "installationId": "12345678",
    "owner": "your-org",
    "repo": "your-docs-repo",
    "branch": "main",
    "docs": "docs",
    "siteUrl": "https://docs.your-domain.com"
  }
}'
```

##### Field reference

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `label` | string | Yes | A human-readable label for this integration. |
| `provider` | string | Yes | Must be `mintlify`. |
| `platform` | string | Yes | Must be `github`. |
| `credentials.installationId` | string | Yes | The GitHub App installation ID, provided during app installation. |
| `credentials.owner` | string | No* | The GitHub organization or username that owns the repository (e.g., `your-org`). |
| `credentials.repo` | string | No* | The repository name (e.g., `your-docs-repo`). |
| `credentials.branch` | string | No | The branch to track. Defaults to `main` when omitted. |
| `credentials.docs` | string | No | The docs folder relative to the repo root (e.g., `docs`). When omitted, the entire repository is scanned for MDX/MD files. |
| `credentials.siteUrl` | string | No | The public URL of your docs site (e.g., `https://docs.your-domain.com`). When set, article links in LaunchBrightly point here instead of GitHub. |

*`owner` and `repo` can be omitted on initial creation and set later via `PUT /integration`. The verification endpoint returns all accessible repositories and branches so you can present a picker in your UI before finalizing the configuration.

### Success Response

##### Code: `200`

```json
{
  "id": "d9e45598-d24d-40d8-baf6-33b6185c61b3",
  "createdAt": "2026-06-15T10:30:00.000Z",
  "updatedAt": "2026-06-15T10:30:00.000Z",
  "message": "The Integration credentials have been successfully created."
}
```

### Error Response - Code: `422`

```json
{
  "errors": [
    "The platform is not supported. Supported platforms: github, helpcenter, cloud"
  ]
}
```

---

## Update an existing integration

`PUT /integration`

The Mintlify integration supports **partial credential updates**. You can send only the fields you want to change - they are merged with the stored credentials automatically. This is useful for updating `owner`, `repo`, or `branch` after initial creation.

### Request

##### cURL

```bash
curl --location --request PUT 'https://api.launchbrightly.com/integration' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
  "id": "d9e45598-d24d-40d8-baf6-33b6185c61b3",
  "label": "Acme Docs (Mintlify)",
  "provider": "mintlify",
  "platform": "github",
  "credentials": {
    "owner": "your-org",
    "repo": "your-docs-repo",
    "branch": "production"
  }
}'
```

Fields not included in `credentials` (like `installationId`) retain their stored values.

### Success Response

##### Code: `200`

```json
{
  "id": "d9e45598-d24d-40d8-baf6-33b6185c61b3",
  "createdAt": "2026-06-15T10:30:00.000Z",
  "updatedAt": "2026-06-15T10:45:00.000Z",
  "message": "The Integration credentials have been successfully updated."
}
```

---

## Verify connection

`POST /integration/verify`

Verifies that the GitHub App installation is valid and returns the list of accessible repositories and their branches. Use this to build a repository/branch picker before finalizing the integration.

### Request

##### cURL

```bash
curl --location --request POST 'https://api.launchbrightly.com/integration/verify' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
  "integrationId": "d9e45598-d24d-40d8-baf6-33b6185c61b3"
}'
```

### Success Response

##### Code: `200`

```json
{
  "isConnectionSuccessful": true,
  "message": "The GitHub credentials have been successfully validated.",
  "meta": [
    {
      "owner": "your-org",
      "repo": "your-docs-repo",
      "branches": ["main", "staging", "production"]
    },
    {
      "owner": "your-org",
      "repo": "blog",
      "branches": ["main"]
    }
  ]
}
```

The `meta` array contains every repository accessible to the GitHub App installation, along with their branch names.

### Failure Response

##### Condition: Installation ID not found or the GitHub App is not installed

```json
{
  "isConnectionSuccessful": false,
  "message": "Installation not found or this GitHub App is not installed for that installation id."
}
```

---

## Import articles from a Mintlify repo

`POST /helpcenter/import`

Imports all MDX and Markdown articles from the configured repository and branch. The import process scans the `docs` directory (or the entire repo if `docs` is not set), extracts frontmatter metadata and inline images and creates article records in LaunchBrightly.

### Request

##### cURL

```bash
curl --location --request POST 'https://api.launchbrightly.com/helpcenter/import' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
  "integrationId": "d9e45598-d24d-40d8-baf6-33b6185c61b3"
}'
```

### Success Response

##### Code: `202 Accepted`

```json
{
  "import_job_id": "5592eac6-dfaf-47b8-890a-b6d7cdd7b0ac",
  "platform": "github",
  "message": "Your import request has been received successfully"
}
```

Use `GET /helpcenter/import/:import_job_id` to poll for import progress. See [Import using Auth](https://docs.launchbrightly.com/help-center-sync-api/import-auth.html) for full response details.

#### INFO

GitHub articles use the file path as their `external_article_id` (e.g., `docs/getting-started.mdx`). This is the same identifier you'll use as the `articleId` when syncing screenshots.

---

## Sync screenshots to Mintlify

`POST /helpcenter/article/async`

Screenshot updates for Mintlify integrations **must** use the asynchronous endpoint. The synchronous `PUT /helpcenter/article/:id` endpoint is not supported for GitHub integrations and returns a `501` error.

See [Asynchronous Article Updates](https://docs.launchbrightly.com/help-center-sync-api/async-article-updates.html) for full endpoint documentation.

### How it works

When you submit a batch of screenshot updates targeting a Mintlify integration:

1. **All jobs are coalesced into a single SQS message** keyed by `articleRequestId`, rather than one message per screenshot. This ensures one pull request per batch.

2. **The worker creates a branch** named `lb-<articleRequestId>` off the configured base branch.

3. **For each article in the batch**, the worker reads the live MDX/MD content from the base branch, matches incoming screenshots against the images in the file (using the standard metadata → hash priority), downloads the replacement image and writes it as a new blob.

4. **One commit is created per article** with the message format: `screenshot: update N image(s) in <path>`.

5. **A pull request is opened** from the working branch back to the base branch, titled with a summary of the changes.

6. **If `automergePR` is `true`**, the pull request is automatically merged after creation.

### Request example

##### cURL

```bash
curl --location --request POST 'https://api.launchbrightly.com/helpcenter/article/async' \
--header 'x-api-key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
  "integrationId": "d9e45598-d24d-40d8-baf6-33b6185c61b3",
  "automergePR": true,
  "data": [
    {
      "articleId": "docs/billing/overview.mdx",
      "screenshots": [
        {
          "metadata": { "name": "John", "surname": "Doe" },
          "hash": "4d441888f21eceed2443eef4ba9b4e4d6c198f86904c258d476fed10a6b2e555",
          "name": "billing-dashboard.png",
          "url": "https://your-bucket.s3.us-east-1.amazonaws.com/your-team/2026-01-15/screenshot-001.png"
        }
      ]
    },
    {
      "articleId": "docs/settings/general.mdx",
      "screenshots": [
        {
          "metadata": { "name": "Jane" },
          "hash": "b6975b10b36df3cc8e41b16a9be8c4f691aa1a2059d3dbcfde31d16fe6d5f65d",
          "name": "settings-page.png",
          "url": "https://your-bucket.s3.us-east-1.amazonaws.com/your-team/2026-01-15/screenshot-002.png"
        }
      ]
    }
  ]
}'
```

#### INFO

The `articleId` for Mintlify integrations is the **file path** within the repository (e.g., `docs/billing/overview.mdx`), not a numeric ID. This is the same path returned as `external_article_id` during import.

### Success Response

##### Code: `202 Accepted`

```json
{
  "articleRequestId": "c3a1f9e2-7b4d-4e8a-9f5c-2d6b8a3e1f7d",
  "jobs": [
    {
      "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "status": "pending",
      "createdAt": "2026-06-15T10:30:00.000Z"
    },
    {
      "id": "f9e8d7c6-5b4a-3210-fedc-ba9876543210",
      "status": "pending",
      "createdAt": "2026-06-15T10:30:00.000Z"
    }
  ]
}
```

### Polling response (GitHub-specific fields)

When polling `GET /helpcenter/article/request/:articleRequestId` for a Mintlify batch, the response includes GitHub-specific fields alongside the standard `summary` and `jobs`:

##### cURL

```bash
curl --location --request GET 'https://api.launchbrightly.com/helpcenter/article/request/c3a1f9e2-7b4d-4e8a-9f5c-2d6b8a3e1f7d' \
--header 'x-api-key: YOUR_API_KEY'
```

##### Code: `200 OK`

```json
{
  "summary": {
    "total": "2",
    "pending": "0",
    "completed": "2",
    "failed": "0",
    "delayed": "0"
  },
  "pullRequestUrl": "https://github.com/your-org/your-docs-repo/pull/42",
  "pullRequestMerged": true,
  "branch": "lb-c3a1f9e2-7b4d-4e8a-9f5c-2d6b8a3e1f7d",
  "jobs": [
    {
      "id": "a1b2c3d4-5e6f-7890-abcd-ef1234567890",
      "externalArticleId": "docs/billing/overview.mdx",
      "name": "billing-dashboard.png",
      "metadata": { "name": "John", "surname": "Doe" },
      "hash": "4d441888f21eceed2443eef4ba9b4e4d6c198f86904c258d476fed10a6b2e555",
      "matchType": "metadata",
      "status": "completed",
      "createdAt": "2026-06-15T10:30:00.000Z",
      "updatedAt": "2026-06-15T10:30:15.000Z"
    },
    {
      "id": "f9e8d7c6-5b4a-3210-fedc-ba9876543210",
      "externalArticleId": "docs/settings/general.mdx",
      "name": "settings-page.png",
      "metadata": { "name": "Jane" },
      "hash": "b6975b10b36df3cc8e41b16a9be8c4f691aa1a2059d3dbcfde31d16fe6d5f65d",
      "matchType": "name",
      "status": "completed",
      "createdAt": "2026-06-15T10:30:00.000Z",
      "updatedAt": "2026-06-15T10:30:18.000Z"
    }
  ]
}
```

| Field | Description |
| --- | --- |
| `pullRequestUrl` | Full URL to the GitHub pull request. `null` if no images were matched. |
| `pullRequestMerged` | `true` if the PR was auto-merged (requires `automergePR: true`). |
| `branch` | The working branch name: `lb-<articleRequestId>`. |

---

## Key differences from other integrations

| Aspect | Zendesk / Intercom / etc. | Mintlify (GitHub) |
| --- | --- | --- |
| **Integration platform** | `helpcenter` | `github` |
| **Integration provider** | `zendesk`, `intercom`, etc. | `mintlify` |
| **Article identifier** | Numeric external article ID | File path (e.g., `docs/overview.mdx`) |
| **Sync method** | Async POST (one SQS message per screenshot) | Async POST (one SQS message per batch) |
| **Output** | Direct API call to help center | Git commit + pull request |
| **Duplicate detection** | 30s delay + retry per article | Not needed (single batch processing) |
| **Sync PUT endpoint** | Supported (legacy) | Not supported (returns `501`) |

---

## Supported file types

| Extension | Type |
| --- | --- |
| `.md` | Markdown |
| `.mdx` | MDX (Markdown with JSX) |

Files outside the configured `docs` directory (if set) are ignored.

---

## Image matching in MDX files

The worker reads each MDX/MD file from the repository and extracts all image references. It then uses the same matching priority as other integrations:

| Priority | Match Type | How it matches in MDX |
| --- | --- | --- |
| 1st | `metadata` | Compares the screenshot's metadata key-value pairs against PNG metadata embedded in the live image |
| 2nd | `hash` | Compares the pixel hash of the incoming screenshot against the live image |

When a match is found, the replacement image is committed to the repository under the same directory as the original (or under `images/launchbrightly/` for new paths) and the MDX image reference is updated accordingly.

---

## HTTP status codes

| Code | Endpoint | Description |
| --- | --- | --- |
| `200` | `POST /integration`, `PUT /integration`, `POST /integration/verify`, `GET /helpcenter/article/request/:id` | Success |
| `202` | `POST /helpcenter/import`, `POST /helpcenter/article/async` | Accepted for async processing |
| `403` | All | Missing or invalid API key |
| `404` | `GET /helpcenter/article/request/:id` | `articleRequestId` not found |
| `422` | `POST /integration`, `PUT /integration`, `POST /helpcenter/article/async` | Validation error |
| `500` | All | Unexpected server error |
| `501` | `PUT /helpcenter/article/:id` | GitHub integrations do not support synchronous updates |
