Skip to main content

Manage Media Files via the API

Upload, manage, and use media files (images, audio, video) through the Inrō API. Attach media inline to scenario actions with only a URL, no pre-upload needed.

You can upload and manage the media files (images, audio, video) that your scenario and campaign actions attach. Upload them up front through the API or the MCP media files tool, or attach one inline while you build a scenario by passing a URL, with no separate upload step. That inline path also works when your AI agent builds a scenario for you.

Before you start

You'll need a Pro or Trial account and your API token. See The Inrō Private API: Getting Started for auth.

Manage media files

These endpoints are under /api/v1/media_files:

  • GET /api/v1/media_files lists your media files. Filter by media_type (image, audio, video, and more) and page through the results.

  • POST /api/v1/media_files uploads a file in one of three ways. Provide a file_url that Inrō downloads for you (the media_type is detected automatically), send a multipart file, or send neither to get back a pending file with a single-use upload_url. For that third mode, PUT the raw bytes to the upload_url (no auth header needed, set Content-Type to the file's MIME type) and poll GET /api/v1/media_files/:id until upload_status is ready. The response also includes an upload_page_url you can hand to a person who has the file, and uploads through that page resume where they left off if the connection drops. If the link expires before the upload finishes, call POST /api/v1/media_files/:id/refresh_upload to mint a new one without losing what was already uploaded. You can also add a caption.

  • Set purpose when you upload. messaging (the default) compresses the file for DM attachments (video scaled to 1280 px tall, images to 1920 px). publishing keeps the source resolution and is what you want for anything you'll post as a feed post, reel or story. A file compressed for messaging can't be restored afterwards.

⚠️ Size limits: images, audio and documents up to 25 MB, video up to 250 MB, text files up to 5 MB. Oversized uploads are rejected. - GET /api/v1/media_files/:id fetches one media file by its ID.

Attach media inline to an action

You don't have to upload first. When you create or update a scenario, the media_file field on an action takes one of two shapes:

  • { "id": 123 } references a media file you already uploaded.

  • { "file_url": "https://..." } downloads and stores a new one inline, then links it to the action in the same request.

The same works inside conversion_link objects, so you can give a link card a cover image inline.

Where this works:

  • Scenario actions: over both the API and MCP.

  • Campaign actions: over the API only. (The MCP campaigns tool doesn't carry inline objects, so upload first with POST /api/v1/media_files or the media_files tool, then reference the file by id.)

Have your AI agent attach media

Your agent has the same media_files tool (list, get, create and refresh an upload link), so it can upload a file from a URL or give you an upload page for a file on your computer. And because inline media_file works through the scenarios tool, you can ask it to build a media-rich scenario in one go:

"Create a welcome scenario that sends the image at https://mybrand.com/welcome.jpg when someone DMs me 'hello'"

Your agent calls the scenarios tool with action: create and media_file: { file_url: "..." } on the send-photo action. Inrō downloads the image, stores it, and links it to the action, all in a single request.

🐾 Netsuke's Tips

  • Reusing the same image across many scenarios? Upload it once with POST /api/v1/media_files, then reference it by id instead of passing the URL every time.

  • When you upload with file_url, Inrō reads the file's content type to set media_type. If a file comes back with the wrong type, check that the URL serves the right Content-Type header.

  • For sending media straight to a contact (rather than attaching it to an action), see Send Rich Messages via API & MCP.

What's next?

Did this answer your question?