Manifst Connectors

Connect Manifst to your software development tools to automatically synchronize tickets with your Git activity and receive real-time notifications in Slack and Discord.

Overview

Connectors are configured per project under Settings → Integrations. Only project owners can create or edit connectors.

The GitHub, GitLab, Slack, Discord, Jira and Google Meet connectors are included from the Team plan onwards. Power BI and the REST API belong to the Portfolio plan.

Who gets access

A subscription grants capabilities to the account, never to the project. Being invited to a paying subscriber's project therefore grants no rights over their connectors: every member is assessed on their own plan.

Project memberWhat they can do
Team plan or above See Git links on item pages, trigger a Jira sync, analyse a Meet recording. Configuration remains restricted to project owners.
Starter plan Sees neither the Development panel nor the commit and pull request badges, and cannot drive any connector — even on a project that has active ones.

Their work still feeds the connectors, though: their commits are linked to tickets, their edits are pushed to Jira, their actions fire notifications. The subscriber paid for a complete view of their project's delivery — a teammate's contribution is not removed from it, it simply stays invisible to that teammate.

ConnectorDirectionMain Use Case
GitHub GitHub → Manifst Link commits & PRs to tickets, automatically close stories on merge
GitLab GitLab → Manifst Link commits & merge requests to tickets, automatically close stories on merge
Slack Manifst → Slack Real-time notifications for status changes, sprint updates, and comments
Discord Manifst → Discord Embed notifications in a Discord channel via Incoming Webhook
Power BI / REST API Manifst → Power BI Track and consolidate project data (EVM, costs, backlog, roadmap) in BI reports via REST API v1

GitHub

Automatically link commits and pull requests to your tickets using issue references in commit messages and PR descriptions.

Configuration

  1. In Manifst, open Settings → Integrations → GitHub → Configure.
  2. Copy the displayed secret key (visible only once).
  3. In GitHub, open your repository → Settings → Webhooks → Add webhook.
  4. Payload URL: the URL displayed in Manifst after saving.
  5. Content type: application/json required
  6. Secret: the secret key copied in step 2.
  7. Events: Pushes + Pull requests.
  8. Click Add webhook. GitHub sends a ping event — Manifst responds {"ok":true}.

Push — Link a commit to a ticket

Include a #<PREFIX>-<id> reference in your commit message to automatically link the commit to the matching item.

Syntax
#<PREFIX>-<numeric id>

The prefix is the one shown in front of the item in Manifst. Every ticket type defined in the project is recognised — not just US — along with both roadmap levels:

PrefixTarget
#US-42, #BG-7, …A ticket, per the abbreviations defined in Settings → Ticket types
#EP-12An Epic
#SE-3A Super Epic
The prefix must match the item's actual type: #US-42 links nothing if item 42 is a bug shown as BG-42. Unresolved references show up in the delivery log rather than being linked to the wrong item.
Examples
git commit -m "fix: login form validation #US-42"

git commit -m "feat: add pagination support #US-17 #US-18"

git commit -m "fix: crash on startup #BG-7"

Multiple references in a single commit are supported.

Branch name

The branch name is parsed too, without the hash sign: no commit-message discipline is needed when your naming convention already carries the reference.

git checkout -b feature/US-42-login-form
git checkout -b hotfix/BG-7

The branch then appears in the Development panel of the item, next to commits and pull requests.

Recorded FieldSource
Commit SHAcommit.id
Messagecommit.message (max 500 chars)
URLcommit.url
Authorcommit.author.name
Branchref
A push does not change the ticket status. It only creates a link, shown in the Development panel of the item. To update status automatically, use a Pull Request with auto-close enabled.

Pull Requests

Mention one or more items in the PR title or description, using the same syntax as for commits. The PR's source branch is parsed as well: a PR coming from feature/US-42-… is linked even without an explicit mention.

GitHub's closing keywords (fix, fixes, close, closes, resolve, resolves…) placed in front of a reference are recognised and recorded as a closing intent.

PR Description Example
## Changes
User profile form implementation.

Closes #US-15 #US-23

The link status in Manifst is updated automatically whenever the PR state changes:

GitHub ActionManifst Link Status
opened, reopened, synchronize, editedopen (or draft if the PR is a draft)
converted_to_draftdraft
ready_for_reviewopen
closed (unmerged)closed
closed (merged)merged
The PR's current text is authoritative: removing #US-42 from the description removes the matching link. A link that already triggered an auto-close is kept, so the trace of what changed the status is never erased.

Auto-close stories on merge

When a PR is merged, Manifst can automatically move linked tickets to a designated "Done" column.

To enable this feature:

  1. In Settings → Integrations → GitHub, toggle on Automatically close stories on merge.
  2. Select the destination column from the dropdown list (columns of type "done" in your Kanban board).
  3. Save. Any merged PR referencing a ticket will move the referenced tickets to that column, whatever their prefix.
If a ticket already has the target status, no change is made. The target column must belong to the same project.
Auto-close applies to tickets only. An Epic or Super Epic referenced with #EP- or #SE- is linked to the PR, but its status is never changed: those two levels are not driven by Kanban columns.

Once, at merge time

Closing fires on the event that performs the merge, not on the "merged" state. In practice, if you reopen a ticket by hand afterwards, later editing the PR title or description will not close it again. A human decision is never overwritten by a text change on GitHub.

An automatically closed ticket carries an "auto-closed" note under the matching link, in the Development panel of its page.

GitLab

The same linking as GitHub, applied to merge requests. Both connectors can run side by side on the same project.

Configuration

  1. In Manifst, open Settings → Integrations → GitLab → Configure.
  2. Copy the displayed token (visible only once).
  3. In GitLab, open your project → Settings → Webhooks → Add new webhook.
  4. URL: the one displayed in Manifst after saving.
  5. Secret token: the token copied in step 2.
  6. Trigger: Push events + Merge request events.
  7. Leave Enable SSL verification ticked, then Add webhook.
GitLab's authentication is weaker than GitHub's, and that comes from GitLab, not Manifst. GitHub signs each delivery body (HMAC-SHA256), proving both possession of the secret and the integrity of the content. GitLab merely echoes the token in plain text in a header. Consequences: the received content cannot be verified, and the token is replayable if intercepted. The webhook URL must therefore use HTTPS — over HTTP, the token travels in the clear on every push.

References

The syntax is identical to GitHub: #<PREFIX>-<id> in a commit message, the branch name parsed without a hash sign, and closing keywords recognised. See the GitHub section for details — it is literally the same parsing code.

GitHubGitLab
Pull requestMerge request — shown as !42 in the UI
pull_request eventMerge request events
X-Hub-Signature-256 headerX-Gitlab-Token header
Content type: application/json must be selectedAlways JSON, nothing to set
Manifst stores the merge request's visible number (iid — the one in the URL and in !42), not its instance-wide internal id. Links therefore point at the MR you actually see.

Private repositories and self-managed instances

The connector is inbound: GitLab calls Manifst. A private repository therefore works exactly like a public one — no repository access token is needed, and Manifst never reads your code.

A self-managed instance works too, on one condition: it must be able to reach Manifst's public URL. An instance behind a corporate firewall can often call out even when inbound access is impossible — what matters is the direction of travel.

One nuance about links: the ones recorded point at your repository. On a private repository, a Manifst member without GitLab access will land on a login page. That is the expected behaviour — repository permissions belong to GitLab.

Slack

Receive notifications in a Slack channel for important project events.

Configuration

  1. In Slack, create an Incoming Webhook at api.slack.com/apps → your app → Incoming Webhooks → Add New Webhook to Workspace. Select the target channel.
  2. Copy the generated Webhook URL (format: https://hooks.slack.com/services/T…/B…/…).
  3. In Manifst, open Settings → Integrations → Slack → Configure.
  4. Paste the URL into the Webhook URL field.
  5. Check the desired events.
  6. Click Test Connection to verify message delivery, then click Save.
Only https://hooks.slack.com/services/… URLs are accepted. All other URLs are rejected for security reasons.

Available Events

story_status_changed
Triggered when a ticket status changes. Indicates former status, new status, and ticket title.
story_assigned
Triggered when a ticket is assigned (or reassigned) to a team member.
new_comment
Triggered on every new comment. Includes a preview (max 120 chars, HTML stripped).
sprint_started
Triggered when a sprint moves from Planning to Active.
sprint_ended
Triggered when a sprint is marked as Completed.
pr_merged
Triggered when a GitHub pull request referencing one or more items is merged. The message shows the target branch, who merged it and the linked items. Requires the GitHub connector on the same project.

Message Format

Messages use Slack mrkdwn formatting. Here are examples for each event:

story_status_changed
🔄 *Status updated* — *Update user profile*
Backlog → In progress
story_assigned
👤 *Story assigned* — *Add pagination*
Assigned to *Marie Dupont*
new_comment
💬 *New comment* on *Update user profile*
By *Jean Martin*: Form must handle profile avatar upload…
sprint_started
🚀 *Sprint started* — *Sprint 3 — Auth & Profile*
sprint_ended
✅ *Sprint ended* — *Sprint 3 — Auth & Profile*

Discord

Receive embed notifications in a Discord channel for key project events.

Configuration

  1. In Discord, open your channel → Channel Settings → Integrations → Webhooks → New Webhook.
  2. Name the webhook (e.g. Manifst), select the channel, then click Copy Webhook URL.
    The URL format is https://discord.com/api/webhooks/<id>/<token>.
  3. In Manifst, open Settings → Integrations → Discord → Configure.
  4. Paste the URL into the Webhook URL field.
  5. Check the desired events.
  6. Click Test to send a test message to Discord, then click Save.
Only https://discord.com/api/webhooks/… URLs are accepted. All other URLs are rejected to prevent SSRF vulnerabilities.

Available Events

Events are identical to the Slack connector — a single event can trigger both Slack and Discord webhooks simultaneously if both are enabled.

story_status_changed
Triggered when a ticket status changes. Embed displays old/new status and ticket title.
story_assigned
Triggered when a ticket is assigned or reassigned to a team member.
new_comment
Triggered on new comments. Embed includes a snippet of the comment.
sprint_started
Triggered when a sprint becomes active.
sprint_ended
Triggered when a sprint is completed.
pr_merged
Triggered when a GitHub pull request referencing one or more items is merged. Requires the GitHub connector on the same project.

Embed Format

Discord notifications utilize embeds with distinct sidebar colors per event type. Text supports standard Discord Markdown (**bold**, *italic*, `code`).

EventColor
sprint_started#57F287 — Green
sprint_ended#FEE75C — Yellow
new_comment#EB459E — Pink
story_status_changed, story_assigned#5865F2 — Blurple
pr_merged#8B5CF6 — Violet

Sample Discord webhook JSON payload:

POST https://discord.com/api/webhooks/<id>/<token>
{
  "embeds": [{
    "description": "🔄 **Story updated** — **Update user profile**\nStatus: `Backlog` → `In progress`",
    "color": 5793266
  }]
}
Discord returns HTTP 204 No Content on success (unlike Slack which returns 200 ok). Manifst treats any response other than 204 as a delivery error.

Power BI / REST API

Connect Power BI Desktop (or any BI tool) to the v1 REST API to build custom dashboards and consolidate multi-project tracking: Earned Value Management (EVM), costs, backlog, and roadmap.

This connector requires no configuration in Manifst — it consists of consuming the v1 API directly from Power BI. Refer to the API Documentation for the full list of endpoints.

Key & Prerequisites

The key is shown only once upon creation. Keep it secure and never expose it in client-side code.

Before configuring Power BI, test your key with a quick PowerShell command — if it returns JSON {"data":[…]}, you are ready:

curl.exe -H "Authorization: Bearer mfst_live_YOUR_KEY" https://manifst.net/api/v1/projects

Connecting Power BI Desktop

The API authenticates via an Authorization: Bearer header. The most reliable pattern is declaring it inside a Power Query M script using Web.Contents (compatible with scheduled cloud refresh). Open Home → Transform data → New Source → Blank Query → Advanced Editor and paste:

Project EVM Indicators Query
let
    BaseUrl = "https://manifst.net/api/v1",
    ApiKey  = "mfst_live_YOUR_KEY",
    Source  = Json.Document(
        Web.Contents(BaseUrl, [
            RelativePath = "finance",
            Query   = [ project = "PROJECT_UUID" ],
            Headers = [ Authorization = "Bearer " & ApiKey ]
        ])
    )
in
    Source[data]

When Power BI prompts for authentication credentials, select Anonymous: credentials are passed directly via the HTTP header. Obtain your project UUID from the /projects endpoint.

Always declare headers using Web.Contents(BaseUrl, [RelativePath=…, Headers=…]) instead of the GUI wizard to avoid "Dynamic Data Source" errors during scheduled service refreshes.

Portfolio Roll-up (Multi-Project)

The /portfolio/finance endpoint aggregates EVM data for all accessible projects in a single request — perfect for program management. It returns a consolidated totals object plus project-level details.

"One project per row" Table Query
let
    BaseUrl = "https://manifst.net/api/v1",
    ApiKey  = "mfst_live_YOUR_KEY",
    Source  = Json.Document(
        Web.Contents(BaseUrl, [
            RelativePath = "portfolio/finance",
            Headers = [ Authorization = "Bearer " & ApiKey ]
        ])
    ),
    Projects = Table.FromRecords(Source[data][projects])
in
    Projects

The consolidated roll-up block is accessible via Source[data][totals] (Σ BAC, portfolio CPI/SPI, total VAC…). To filter for specific projects, add Query = [ projects = "uuid1,uuid2" ].

EVM portfolio calculations include only projects with a declared BAC (Finance → Budget tab). Overall actual costs remain available via ac_all and engaged_all.

Incremental Refresh & Pagination

Large endpoints /tickets and /time-entries support pagination and date filtering passed in the query parameters:

ParameterRole
updated_sinceReturns items updated since a specific date (YYYY-MM-DD) — useful for incremental refresh.
page / per_pagePagination (default 100, max 500 per page). The meta.total property gives the true total count.
            RelativePath = "tickets",
            Query = [ project = "PROJECT_UUID", updated_since = "2026-07-01", per_page = "500", page = "1" ],
            Headers = [ Authorization = "Bearer " & ApiKey ]
API Limits: 1,000 requests/hour and 10,000 requests/month per key. Rate limit status headers are included in every API response.

Troubleshooting

SymptomCause & Solution
401 MISSING_API_KEYAuthorization header not sent. Use Web.Contents(BaseUrl, [Headers=…]) in Power Query M script.
401 INVALID_API_KEYKey invalid, revoked, or expired. Regenerate under Settings → API Keys.
403 INSUFFICIENT_SCOPEMissing required scopes (finance:read, roadmap:read…). Recreate key with appropriate permissions.
403 PLAN_REQUIREDREST API requires the Portfolio plan. Verify account subscription.
429 RATE_LIMIT_EXCEEDEDHourly or monthly quota exceeded. Respect Retry-After response header.
Works in Desktop but fails on scheduled service refreshDynamic data source error from GUI wizard. Use RelativePath and Headers parameters in M script.

Security

GitHub — HMAC Verification

GitHub requests are signed with HMAC-SHA256 via the X-Hub-Signature-256 header. Invalid signatures are rejected with HTTP 401.

If your secret key is compromised, regenerate it immediately under Settings → Integrations → GitHub → Regenerate secret, and update GitHub Webhook settings.

Slack — SSRF Protection

Only https://hooks.slack.com/services/… endpoints are accepted. Webhooks pointing to local or private IP spaces are rejected.

Discord — SSRF Protection

Only https://discord.com/api/webhooks/<id>/<token> URLs are accepted. Tokens must match [A-Za-z0-9_-] patterns.

Rate Limiting

The Test Connection button is rate-limited to 5 calls per minute per user per project.

Slack & Discord Circuit Breaker

If delivery fails 5 consecutive times, the connector is automatically disabled to prevent silent errors. Re-enable it once the webhook URL is fixed.

FAQ

GitHub webhook returns ignored: invalid_json

Set GitHub webhook Content type to application/json in GitHub repository Settings → Webhooks.

Webhook returns ignored: integration_not_configured

The GitHub integration has not been created or was deleted for this project. Set it up in Settings → Integrations.

Commits are linked (refs_linked: 1) but story status does not change

A push links commits for reference without altering story status. To close stories automatically, use a merged Pull Request with auto-close enabled.

I am not receiving Slack notifications

Can I connect multiple GitHub repositories?

A single GitHub connector per project is supported. For multi-repo setups, configure multiple GitHub webhooks targeting the same Manifst URL.

A teammate cannot see the "Development" panel

Connectors are included from the Team plan onwards, and the capability is assessed on their subscription — not the project owner's, and not the project itself. A member on the Starter plan therefore sees neither the panel nor the commit badges, even on a project whose connector works fine. Their own commits are still linked, and remain visible to members who are entitled to them.

Lost GitHub secret key

Secrets are shown only once upon creation. If lost, click Regenerate Secret in Manifst and update the value in GitHub.

Not receiving Discord notifications

Can Slack and Discord connectors be active simultaneously?

Yes. Both connectors function independently and send notifications simultaneously if configured for the same event.

Is the Discord token visible to non-owner project members?

No. Webhook URLs are masked in the API for non-owners (only the first 4 token characters are visible). Only project owners see the full URL.