Skip to main content
GraphQL requests carry JSON, so a binary file cannot travel in one. The Mighty API uploads media through a REST endpoint instead: you POST the bytes and the response gives you an asset ID. Pass that ID to a GraphQL mutation to attach the asset to a post or article, a chat message, a member’s profile, an event, or a Space or Network image slot. See Attaching uploaded assets for post and comment body restrictions.
Video and audio go through the createUploadSession mutation, not this endpoint. That path uploads in chunks and puts the file through transcoding, so the result plays in the product. This endpoint stores a single file in one request.

Endpoint

The {network_id} segment takes either the Network’s numeric ID (for example 12345) or its subdomain slug (for example my-community for my-community.mn.co), the same two forms the GraphQL endpoint accepts. Send a file as multipart/form-data. A base64 or source_url upload carries no binary, so it can be sent as ordinary form fields instead.
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).

Authentication and scopes

Authenticate the same way you authenticate a GraphQL request: pass an OAuth access token or an Admin API key as a Bearer token.
The credential has to carry one of two scopes. A member token needs write:assets. A Host credential, such as an Admin API key, can carry host:write:network_assets instead. Either one satisfies the endpoint, and a credential holding neither receives a 403. See the Authentication Guide for the OAuth flows and OAuth Applications — Scopes for the full scope catalog.

Request fields

Every upload names its source with exactly one of file, base64, or source_url. Everything else is optional. Send metadata either as nested form fields (metadata[is_main_image]=true) or as a JSON object string (metadata={"is_main_image":true}). Both keys are declarations, so false and omitting the key mean the same thing, and keys other than the two above are dropped.

Asset styles

asset_style tells Mighty what the asset is for, which decides how it is stored and processed. Pick the style that matches where the asset will end up.
The destination slot determines the final style. A detached asset can be restyled and attached in place; reusing an asset already attached to other content can create a copy.For createEvent and updateEvent, thumbnailId cannot name an asset styled cinema_header, and thumbnailId and headerId must name different assets. Pass headerId alone to use the header on the event card when the event has no separate thumbnail.
An asset_style outside the table is rejected with a 400. So are the video and audio styles, which return a 400 pointing you at createUploadSession.

Limits and validation

Size. A file or base64 upload larger than 25 MB is rejected with a 413 before anything is stored. A source_url has no size until it is fetched, so a fetched file over 25 MB is rejected with a 400 and the message Validation failed: This file must be 25MB or smaller. Content types. Uploads are checked against an allowlist of common image types (JPEG, PNG, GIF, WebP, AVIF, HEIC, HEIF, TIFF, BMP), audio types (MP3, M4A, WAV, FLAC, AIFF), video types (MP4, MOV), and document types (PDF, plain text, CSV, Word, Excel, PowerPoint, Pages). SVG, HTML, and script or executable files are refused whatever content type they declare, because they can carry executable content. Source URLs. A source_url has to use http or https. Loopback addresses are rejected with Invalid URL, and private or internal addresses are refused by the server’s outbound request filter, so the URL has to be reachable from the public internet. The fetch gives up after 5 seconds to connect and 5 seconds to read. A failed download returns 400 with validation details that can include missing-file, missing-content-type, and download errors. An empty stored file can return This file is empty or failed to upload. Please try again. Main image. For file and base64 uploads, metadata[is_main_image] is kept only when the declared content type or filename extension identifies JPEG, PNG, GIF, WebP, AVIF, HEIC, or HEIF. Either signal is enough. Other formats, including accepted image uploads such as TIFF and BMP, lose the key without failing the request. A source_url upload skips this check and retains the declaration regardless of the fetched file’s type.

Response

A successful upload returns 201 with the stored asset.

Mapping from the Admin API

If you are moving an upload call over from the Admin API, its AssetResponse fields land here as follows.

Errors

Endpoint errors return a JSON body of the shape { "error": "..." }. The bot-protection challenge described above is an HTML response.

Attaching uploaded assets

For a post or article, pass the upload response’s id in assetIds on createPost or updatePost. Their body accepts plain text and formatting HTML. Tags such as <img>, <a>, and <iframe> are rejected, even when they include an asset ID. On updatePost, assetIds replaces the attachment list. Include all IDs you want to keep, or omit assetIds to leave attachments unchanged. Comments have a separate body format: createComment and updateComment sanitize the HTML you send and remove iframes. Neither mutation exposes an assetIds argument.

Examples

Upload a file, mark it as the content’s main image, and record its aspect ratio:
Upload from a URL Mighty fetches for you:

Next steps

Mighty API

Attach the asset with a GraphQL mutation.

Authentication

Get a token that carries an asset write scope.