Upload media file
curl --request POST \
--url https://app.getkavio.app/api/posts/{post}/media \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'import requests
url = "https://app.getkavio.app/api/posts/{post}/media"
payload = {}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({})
};
fetch('https://app.getkavio.app/api/posts/{post}/media', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.getkavio.app/api/posts/{post}/media",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.getkavio.app/api/posts/{post}/media"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.getkavio.app/api/posts/{post}/media")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.getkavio.app/api/posts/{post}/media")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_bodyPosts
Upload media file
Upload an image or video from your machine and attach it to a post.
POST
/
posts
/
{post}
/
media
Upload media file
curl --request POST \
--url https://app.getkavio.app/api/posts/{post}/media \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{}'import requests
url = "https://app.getkavio.app/api/posts/{post}/media"
payload = {}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({})
};
fetch('https://app.getkavio.app/api/posts/{post}/media', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.getkavio.app/api/posts/{post}/media",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.getkavio.app/api/posts/{post}/media"
payload := strings.NewReader("{}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.getkavio.app/api/posts/{post}/media")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.getkavio.app/api/posts/{post}/media")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"
response = http.request(request)
puts response.read_bodyFor attaching media from a public URL instead of uploading bytes, use
Supported media types:
POST /posts/{post}/media/from-url.
Path parameters
string
required
The UUID of the post to attach the file to.
Request
Send asmultipart/form-data with a single media field.
file
required
The file to upload. Must be one of the allowed types:
- Images:
image/jpeg,image/png,image/gif,image/webp- up to 10 MB - Videos:
video/mp4,video/quicktime(MOV) - up to 1 GB
Behaviour
- The post must belong to the caller’s current workspace; otherwise the response is
404. - The file’s MIME type is intersected with the platforms enabled on the post. For example, uploading an image to a TikTok-only post returns
422unless the post targetstiktok_photo. - Per-type size caps are enforced after MIME detection. A video over 1 GB returns
422even if the request’s overall cap allowed it. - PNG and WebP still images are normalized to JPEG (q100) at storage time for universal platform compatibility. GIF is preserved (animation kept for X / Bluesky / Mastodon). MP4 and MOV videos are stored as-is.
- The new media is stored under
medias/{uuid}.{ext}on the configured filesystem disk (local,s3, orr2) and appended to the post’smedia[]array.
Response
Returns the updated post — same shape asGET /posts/{post}, with the newly-uploaded item in media[].
On validation failure (unsupported type, file too large, no enabled platform accepts the type) the response is 422 with errors.media[].
curl -X POST https://app.getkavio.app/api/posts/9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c/media \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Accept: application/json" \
-F "media=@./photo.jpg"
{
"id": "9f1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"content": "Launch day!",
"media": [
{
"id": "01HX1A2B3C4D5E6F7G8H9I0J1K",
"path": "medias/2681a1bf-131f-41b1-9866-755c1cb51f97.jpg",
"url": "https://media.getkavio.app/medias/2681a1bf-131f-41b1-9866-755c1cb51f97.jpg",
"type": "image",
"mime_type": "image/jpeg",
"original_filename": "photo.jpg"
}
],
"status": "draft",
"scheduled_at": null,
"published_at": null,
"platforms": [],
"labels": [],
"created_at": "2025-01-14 09:00:00",
"updated_at": "2025-01-14 09:30:00"
}

