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

# Mighty API

> The Member API and Admin API in one GraphQL API for custom clients, integrations, and back-office tools on Mighty Networks

<Note>
  Every change to the published schema is recorded on the [changelog](/api/changelog), and breaking changes are deprecated and announced there before they take effect. Check it before you upgrade an integration.
</Note>

<Card title="Explore the schema now" icon="compass" href="/api/graphql-explorer" horizontal>
  Browse every type and field, and run queries against generated sample data in the **GraphQL Schema Explorer**. No tokens will be used, and no Mighty Network of your own is required.
</Card>

<span id="about-the-headless-api" />

## About the Mighty API

The Mighty API brings the **Member API** and **Admin API** together in one **GraphQL** API, built on the same surface area that powers the official Mighty Networks clients. It covers the host- and member-facing product surface end to end, and it grows with the product. Use it to build member experiences (custom apps, embeds, integrations) and administrative tools for hosts and admins.

Both use the same GraphQL endpoint and OAuth authentication. Your token's user permissions and approved scopes determine which member and admin operations you can perform.

The separate [Admin REST API](/admin-api) provides REST endpoints for server-to-server administrative automation.

The Mighty API operates in the context of an authenticated user (member, moderator, or host) and grants the same access that user has in the product. With a host or admin token, that includes administrative reads and writes; with a member token, it's limited to what that member can see and do.

Use the Mighty API when you want to:

* Build a custom client (web, mobile, embed) that surfaces a Network's content to its members
* Build host-facing tools, dashboards, or admin consoles that need data the Admin REST API doesn't expose
* Power a third-party integration that acts on behalf of a specific user (member, moderator, or host)
* Query exactly the fields you need in a single round trip, including nested associations

### What's in the schema today

The Mighty API covers the host- and member-facing product surface end to end. At a glance, the public schema exposes:

* **Network & branding** — Network settings and updates (including landing and home space configuration and feature toggles), the branding theme, custom domains (validate, register, publish, remove), Pinned Links in the navigation menu, payment currencies, the connected Stripe account, and the Network's own Mighty Networks billing plan and enabled features
* **Members** — the authenticated viewer (`me`), the member roster with filtering and single-member lookup; member profile updates, removal, ban, and account deletion; membership role and status (read and update); member-to-member follows; profile social links; custom fields (definitions, options, and member answers) and profile questions
* **Spaces & structure** — spaces (create, update, delete, reorder, move between collections), space memberships, spaces collections, space templates (read-only), live spaces, featured and welcome pins, and discovery-page gallery sections
* **Posts & content** — posts, threaded comments, reactions, tags (including bulk member tagging), polls and poll answers, announcements, saved posts, embedded link previews, the ranked member feed, and media assets (including uploads)
* **Events** — events with recurrence rules, per-occurrence overrides and cancellations, RSVPs, event images (thumbnail and header), and the venue and address for in-person events
* **Chat** — space group chats: list conversations, send and delete messages, mark conversations read, react to messages, and bookmark conversations. Member-to-member direct messages and reply threads are exposed with the member's explicit consent via the `read:chats` and `write:chats` scopes — a token reaches only its own user's conversations.
* **Commerce** — payment plans (create, update, publish, unpublish, archive), subscription groups, member subscriptions (list, cancel), one-time purchases (list, void), promo codes, income reports, and gifts with recognition leaderboards
* **Courses & learning** — courses and coursework (create, update, publish, reorder), member course and video progress, and quizzes (answering, completion, and attempt reporting)
* **Growth & onboarding** — invites (create, resend, revoke), join requests (approve, reject, bulk update), leads (read-only) and waitlists, the Ambassador program (referral stats and the recruitment announcement), the welcome checklist, and custom onboarding steps
* **Marketing & member data** — member segments, marketing audiences, and marketing banners
* **Moderation & safety** — member reports (file, list, clear), the email blocklist, member-to-member blocks, content reporting for posts, comments, and chat messages, and post, prompt, and space muting
* **Gamification** — badges (definitions and member assignment), daily-visit streaks, points balances, and gift leaderboards
* **Notifications** — the viewer's notification inbox (list, mark read or unread) and notification delivery settings
* **Automation & integrations** — automation rules with execution logs, outbound webhooks, and OAuth application management
* **Search** — cross-entity search with typed result filtering

Availability of plan-gated features (for example webhooks, marketing audiences, or Pinned Links) follows the Network's Mighty Networks plan.

Everything in the schema is introspectable — see [Schema and Introspection](#schema-and-introspection) for SDL and introspection endpoints. The set above will continue to grow.

## Endpoint

All GraphQL requests are issued as `POST` to a single per-network endpoint:

```
https://api.mn.co/networks/:network_id_or_subdomain/graphql
```

The path segment `:network_id_or_subdomain` accepts either:

* The Network's numeric ID (e.g. `12345`)
* The Network's subdomain (e.g. `my-community` for `my-community.mn.co`)

Both forms resolve to the same Network and execute against the same schema.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.mn.co/networks/my-community/graphql \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "query": "query { me { id name } }"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
    `https://api.mn.co/networks/${NETWORK}/graphql`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${ACCESS_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        query: `query { me { id name } }`
      })
    }
  );

  const { data, errors } = await response.json();
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      f"https://api.mn.co/networks/{NETWORK}/graphql",
      headers={
          "Authorization": f"Bearer {ACCESS_TOKEN}",
          "Content-Type": "application/json"
      },
      json={"query": "query { me { id name } }"}
  )

  payload = response.json()
  ```
</CodeGroup>

## Authentication

The Mighty API authenticates requests with **OAuth 2.0**. Unlike the [Admin REST API](/admin-api), which uses a long-lived Bearer token tied to a Network admin, the Mighty API issues short-lived access tokens that act on behalf of a specific user in a specific Network — member, moderator, or host. Once you have an access token, you pass it as a Bearer token on every GraphQL request.

<Note>
  OAuth application management is available on the **Scale plan or above**. If you don't see **Integrations > OAuth Applications** in Network Admin, check your Network's plan, or reach out to [Mighty support](mailto:help@mightynetworks.com).
</Note>

### Create an OAuth application

OAuth applications are created and managed by Network hosts under **Network Admin** > **Integrations** > **OAuth Applications**. For the full walkthrough — client types, redirect URI rules, scope catalog, secret rotation, and revocation — see [OAuth Applications](/oauth-applications).

At a glance:

1. Sign in as a host or admin and open **Network Admin**.
2. Go to **Integrations** > **OAuth Applications** and click **New OAuth Application**.
3. Provide a name, choose a client type (public or confidential), register redirect URIs, and select the scopes your app needs.
4. Mighty issues a **Client ID** and (for confidential clients) a **Client Secret**.

See [OAuth Applications](/oauth-applications) for the detailed setup, configuration, and management guide.

### Authorization Code flow

The standard flow for user-facing apps:

1. Redirect the user to the authorization endpoint. OAuth endpoints live on the Network's community host, not on `api.mn.co`:

   ```
   https://:network_subdomain.mn.co/oauth/authorize
     ?response_type=code
     &client_id=YOUR_CLIENT_ID
     &redirect_uri=YOUR_REDIRECT_URI
     &scope=SPACE_SEPARATED_SCOPES
     &state=RANDOM_OPAQUE_STRING
     &code_challenge=PKCE_CHALLENGE
     &code_challenge_method=S256
   ```

   The canonical endpoint URLs are also advertised at `https://:network_subdomain.mn.co/.well-known/oauth-authorization-server` (RFC 8414).

2. The user signs in (if needed) and approves the requested scopes. Mighty redirects back to your `redirect_uri` with a `code` and the `state` you sent. **Verify that the returned `state` exactly matches the cryptographically random value you generated for this request — if it doesn't, reject the callback and do not exchange the code.** This is your CSRF defense.

3. Exchange the code for an access token:

   ```bash theme={null}
   curl https://:network_subdomain.mn.co/oauth/token \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=authorization_code" \
     -d "code=AUTH_CODE_FROM_REDIRECT" \
     -d "redirect_uri=YOUR_REDIRECT_URI" \
     -d "client_id=YOUR_CLIENT_ID" \
     -d "client_secret=YOUR_CLIENT_SECRET" \
     -d "code_verifier=PKCE_VERIFIER"
   ```

   The response contains an `access_token`, `refresh_token`, `expires_in`, and the granted `scope`:

   ```json theme={null}
   {
     "access_token": "eyJhbGciOi...",
     "token_type": "Bearer",
     "expires_in": 3600,
     "refresh_token": "def50200...",
     "scope": "read:network write:posts"
   }
   ```

4. Pass the access token on every GraphQL request:

   ```http theme={null}
   Authorization: Bearer eyJhbGciOi...
   ```

5. When the access token expires, exchange the refresh token for a new one using `grant_type=refresh_token` against the same `/oauth/token` endpoint.

### Token scope and permissions

The access token grants exactly the access the underlying user has in the product, intersected with the scopes the user approved. A member token sees what that member sees; a host or admin token additionally exposes host- and admin-level fields and mutations. Asking for more scopes than your app needs is a smell — request the narrowest set that lets the feature work.

Each query, mutation, field, and type in the GraphQL reference names the scope it requires, so you can choose the narrowest set before you write the request.

Some scopes are consent-required: `read:chats` and `write:chats` expose the member's private conversations, so the consent screen is always shown for them — even on applications configured to skip it.

For full details on the OAuth flows, scope catalog, and token rotation, see the [Authentication Guide](/api/authentication).

## Why GraphQL

GraphQL allows us to expose the full functionality of Mighty's platform, without making assumptions about what kinds of experience you'll build on top of it. A REST surface forces the API designer to enumerate every endpoint, response shape, and association ahead of time — which means the only apps that fit comfortably are the ones we anticipated. That's the wrong shape for a community platform: members, hosts, and integrators put Mighty Networks to uses we couldn't have predicted. A consumer-mobile reader, an internal back-office dashboard, an AI agent that summarizes a space's activity, a custom embed that pulls a single post into a marketing page — these all want different fields, different depths, and different shapes from the same underlying data.

GraphQL lets a client request exactly the fields it needs, traverse associations in one request, and avoid the over-fetching that comes with rigid REST endpoints. The API surface is the schema; what you do with it is up to you.

Concretely, this means:

* **One endpoint, many shapes.** A mobile feed view and a desktop sidebar can hit the same query and select different fields. Same for a CRM sync job and a Discord bot — they ask for what they need and ignore the rest.
* **Typed schema.** Every field, argument, and return type is described in the schema and discoverable via introspection — no out-of-band docs required to know what's possible.
* **Composable queries.** Fetch a post, its author, the author's spaces, and the viewer's permissions on each — in a single round trip. Build the view the app needs, not the view the API designer guessed at.
* **Forward-compatible by default.** New fields and types can be added without breaking existing clients, because clients only see the fields they explicitly ask for. The schema can grow alongside the use cases we haven't thought of yet.

If you're new to GraphQL, the official documentation is the best starting point:

* [graphql.org](https://graphql.org/) — language overview, learning resources, and tooling
* [GraphQL specification](https://spec.graphql.org/) — the formal language and execution spec

### Relay conventions

The schema is designed to be consumed by [Relay](https://relay.dev/)-compatible clients. Concretely:

* Nodes are addressable by a globally unique `id` and reachable through the top-level `node(id: ID!)` field, per the [GraphQL Global Object Identification](https://graphql.org/learn/global-object-identification/) spec.
* Lists are paginated using cursor-based [Connection types](https://relay.dev/graphql/connections.htm) (`edges`, `node`, `pageInfo`) — see also [API Pagination](/api-pagination) for general guidance.
* Mutations follow the [Relay input/payload pattern](https://relay.dev/docs/guides/graphql-server-specification/#mutations): a single `input` argument and a payload type that includes the mutated node(s).

You don't need to use the Relay client — any GraphQL client will work — but if you do, the schema is designed to drop straight in. Useful reading:

* [Relay docs](https://relay.dev/docs/) — client framework guide
* [GraphQL Server Specification](https://relay.dev/docs/guides/graphql-server-specification/) — the conventions the schema follows
* [Cursor Connections Specification](https://relay.dev/graphql/connections.htm) — pagination contract

## Making a Request

A GraphQL request is a `POST` with a JSON body containing `query` and (optionally) `variables` and `operationName`.

<Warning>
  Requests to `api.mn.co` must include a non-empty `User-Agent` header. Requests without one are blocked by bot protection and receive an HTML challenge page with HTTP `403` — a JSON-parse error on the client. We recommend `your-app-name/version (+url)`.
</Warning>

```http theme={null}
POST /networks/my-community/graphql HTTP/1.1
Host: api.mn.co
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
User-Agent: my-app/1.0 (+https://example.com)

{
  "query": "query Post($id: ID!) { network { post(idOrSlug: $id) { id title author { id name } } } }",
  "variables": { "id": "12345" }
}
```

Successful responses return an HTTP `200` with a `data` object:

```json theme={null}
{
  "data": {
    "network": {
      "post": {
        "id": "12345",
        "title": "Welcome to the network",
        "author": { "id": "678", "name": "Jane" }
      }
    }
  }
}
```

Errors are returned as an `errors` array alongside (or instead of) `data`. Each error carries a human-readable `message`, an `extensions.code` for programmatic handling, and (where applicable) a `path` indicating which field produced the error.

```json theme={null}
{
  "data": null,
  "errors": [
    {
      "message": "Post not found",
      "path": ["post"],
      "extensions": { "code": "NOT_FOUND" }
    }
  ]
}
```

<Note>
  GraphQL returns HTTP `200` for most application-level errors. Inspect the `errors` array on every response, not just the HTTP status.
</Note>

## Schema and Introspection

The schema is fully introspectable. You can explore it with any standard GraphQL tool (GraphiQL, Apollo Sandbox, Insomnia, Postman) by pointing the tool at your Network's endpoint and supplying a valid Bearer token.

Two explorers are available, and they do different jobs. The [GraphQL Schema Explorer](/api/graphql-explorer) needs no token and no Network of your own: it runs in your browser against generated mock data, so it is the place to read the schema and shape a query. The hosted GraphiQL explorer below runs real queries against a real Network, and is limited to that Network's hosts.

### GraphiQL Explorer

Network hosts can open the hosted GraphiQL explorer for ad-hoc queries and schema browsing at this URL on their Network's community host:

```
https://:network_subdomain.mn.co/admin/headless-api/explorer
```

Pick one of your Network's OAuth applications and the explorer mints a short-lived access token bound to that application and your host account — there's no Bearer token to paste in. Queries execute against the `api.mn.co` GraphQL endpoint exactly as an integration using that application would.

### Fetching the schema

The fastest way to get a code-generation-ready schema is the dedicated **SDL endpoint**, which returns the Network's GraphQL schema as Schema Definition Language. No authentication required:

```
GET https://api.mn.co/networks/:network_id_or_subdomain/graphql/schema
```

```bash theme={null}
curl https://api.mn.co/networks/my-community/graphql/schema > schema.graphql
```

The response is the public surface filtered to the types, fields, and arguments actually exposed by the GraphQL endpoint — the same surface your queries execute against. Pipe it straight into [`graphql-code-generator`](https://the-guild.dev/graphql/codegen), the [Relay compiler](https://relay.dev/docs/guides/compiler/), or any other tool that consumes SDL.

<Note>
  Start here for codegen. The SDL endpoint is unauthenticated, cacheable, and avoids the round-trip overhead of running a full introspection query.
</Note>

#### Introspection (alternative)

The GraphQL endpoint also responds to the standard [introspection query](https://graphql.org/learn/introspection/), which returns the type system as JSON. Use this if your tooling expects an introspection result instead of SDL, or if you want to query schema metadata at runtime.

A minimal introspection query:

```graphql theme={null}
query {
  __schema {
    types {
      name
      kind
    }
  }
}
```

For a complete dump, use the canonical introspection query published in [`graphql-js`](https://github.com/graphql/graphql-js/blob/main/src/utilities/getIntrospectionQuery.ts) — every popular tool ships a copy of it. Common ways to fetch and persist it:

<CodeGroup>
  ```bash get-graphql-schema (JSON or SDL) theme={null}
  # Install: npm i -g get-graphql-schema
  get-graphql-schema \
    --header "Authorization=Bearer YOUR_ACCESS_TOKEN" \
    https://api.mn.co/networks/my-community/graphql \
    > schema.graphql
  ```

  ```bash Apollo Rover (SDL) theme={null}
  # Install: https://www.apollographql.com/docs/rover/
  APOLLO_HEADERS='{"Authorization":"Bearer YOUR_ACCESS_TOKEN"}' \
    rover graph introspect https://api.mn.co/networks/my-community/graphql \
    > schema.graphql
  ```

  ```bash Raw introspection (JSON) theme={null}
  curl https://api.mn.co/networks/my-community/graphql \
    -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"query":"query IntrospectionQuery { __schema { queryType { name } mutationType { name } subscriptionType { name } types { ...FullType } directives { name description locations args { ...InputValue } } } } fragment FullType on __Type { kind name description fields(includeDeprecated: true) { name description args { ...InputValue } type { ...TypeRef } isDeprecated deprecationReason } inputFields { ...InputValue } interfaces { ...TypeRef } enumValues(includeDeprecated: true) { name description isDeprecated deprecationReason } possibleTypes { ...TypeRef } } fragment InputValue on __InputValue { name description type { ...TypeRef } defaultValue } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name ofType { kind name } } } } } } } }"}' \
    > schema.json
  ```
</CodeGroup>

## Rate Limits

The Mighty API follows the same rate-limit and quota *model* described in the [Admin REST API](/admin-api#rate-limit-and-quota), but its quota is tracked separately — Mighty API usage does not count against the Admin REST API quota and vice versa. The unit of accounting is the GraphQL operation rather than the REST request, and a single query is bounded by the cost limits below.

### Query cost limits

Connections on the query root and on `Network` (`network { posts }`, `network { members }`) page up to 50 at a time. Every connection reached through another connection's page caps a page at 25, including `Post.comments`, `Comment.replies`, `Event.rsvps`, `Member.followers`, `Member.spaces`, `PublicConversation.messages`, and `PrivateConversation.messages`. A `first:` or `last:` above the cap is clamped to it rather than rejected, and `pageInfo` and the cursors are unaffected, so cursor paging still reaches every row.

Before a query runs, its cost is estimated from the most it could return: 1 for each row on every connection page (the `first:` or `last:` you supply, clamped to the page cap, or the page cap when you supply neither), 1 for each object field it reaches, and nothing for scalars. A query estimated above a complexity of 1,500 is rejected before execution, with a top-level error and no `data`, and is billed the 1-unit minimum:

```json theme={null}
{
  "errors": [
    { "message": "Query has complexity of 2703, which exceeds max complexity of 1500" }
  ]
}
```

On a successful response, `extensions.cost.complexity` reports what the query actually cost, so it is the number to watch as you tune a query toward the ceiling.

## Errors

Errors follow the GraphQL [error spec](https://spec.graphql.org/October2021/#sec-Errors). Each error includes a `message`, an `extensions.code` for programmatic handling, and (where applicable) a `path` indicating which field produced the error. The code vocabulary mirrors Apollo Server's defaults, so any GraphQL client library that already understands those codes will work without configuration:

| Code                    | Meaning                                                                                                                                                            |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `UNAUTHENTICATED`       | Missing, expired, or invalid Bearer token. Also returned with HTTP `401` from the bearer-auth layer.                                                               |
| `FORBIDDEN`             | Authenticated, but the viewer lacks permission for the action.                                                                                                     |
| `NOT_FOUND`             | The referenced resource does not exist, or the viewer cannot see it. Visibility checks collapse to `NOT_FOUND` rather than `FORBIDDEN` to avoid leaking existence. |
| `BAD_USER_INPUT`        | An argument failed semantic validation (e.g. malformed cursor, unknown enum value).                                                                                |
| `INTERNAL_SERVER_ERROR` | An unexpected error escaped the resolver. The `message` is generic — details are recorded server-side.                                                             |

Most application-level errors are returned with HTTP `200` and an `errors` array; only `UNAUTHENTICATED` from the bearer-auth layer (missing or invalid Bearer token) and `404` (Network does not exist or Mighty API is not enabled) surface as non-`200` HTTP statuses.

A query rejected before it executes, such as one over the complexity ceiling described in [Query cost limits](#query-cost-limits), is the exception to that vocabulary: it returns a top-level error carrying only a `message`, with no `path` and no `extensions.code`.

<span id="headless-api-vs-admin-api" />

## Mighty API vs. Admin REST API

|              | Mighty API                                                                                          | Admin REST API                                                                            |
| ------------ | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Style        | GraphQL                                                                                             | REST                                                                                      |
| Endpoint     | `api.mn.co/networks/:id_or_subdomain/graphql`                                                       | `api.mn.co/admin/v1/...`                                                                  |
| Acts as      | The authenticated user (member, moderator, or host)                                                 | Network administrator                                                                     |
| Surface area | Broad — the full product surface, including host and admin capabilities                             | Curated — a stable subset for administrative automation                                   |
| Use cases    | Custom clients, member- and host-facing apps, embeds, and integrations that act on behalf of a user | Integrations that use REST endpoints for server-to-server automation and bulk admin tasks |

## Support

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/api/authentication">
    Generate and manage tokens for the Mighty API.
  </Card>

  <Card title="Admin REST API" icon="code" href="/admin-api">
    Compare with the REST-based admin surface.
  </Card>

  <Card title="AI Tools & MCP" icon="sparkles" href="/ai-access">
    Connect these docs to your AI assistant through the docs MCP server, llms.txt, and Markdown page formats.
  </Card>
</CardGroup>
