Cross-post formatter API
Paste one post and see at once where it fits on X, Threads, Bluesky, Mastodon and LinkedIn. Each network counts with its own rules, and you get a ready thread wherever the post is too long.
- Endpoint:
POST https://postboost.co/app/api/tools/cross-post-formatter(operationIdformatCrossPost) - Web tool: postboost.co/tools/cross-post-formatter
- Token: optional (limits)
- MCP: tool
format-cross-postonhttps://postboost.co/mcp/tools
Request
| Field | Type | Default | Description |
|---|---|---|---|
text | string | "" | The post text, up to 10,000 characters. |
networks | array of string | ["x","threads","bluesky","mastodon","linkedin"] | The networks to format for, in the order the result lists them. |
numbering | boolean | false | End each post of a thread with " k/n". |
Call it
- curl
- Python
- Node.js
- PHP
- Go
- Ruby
- Java
- C#
- Rust
- CLI
curl -X POST https://postboost.co/app/api/tools/cross-post-formatter \
-H 'Content-Type: application/json' \
-d '{"text":"Our spring menu is live, thanks @alice for the photos: https://example.com/menu","networks":["x","mastodon","linkedin"]}'
from postboost import ApiClient, Configuration
from postboost.api.free_tools_api import FreeToolsApi
from postboost.models import FreeToolFormatCrossPostRequest
with ApiClient(Configuration()) as client:
api = FreeToolsApi(client)
result = api.format_cross_post(FreeToolFormatCrossPostRequest.from_dict({"text": "Our spring menu is live, thanks @alice for the photos: https://example.com/menu", "networks": ["x", "mastodon", "linkedin"]}))
print(result.to_dict())
import { FreeToolsApi } from 'postboost';
const api = new FreeToolsApi();
const { body } = await api.formatCrossPost({ text: "Our spring menu is live, thanks @alice for the photos: https://example.com/menu", networks: ["x", "mastodon", "linkedin"] });
console.log(body);
use PostBoostClient\Api\FreeToolsApi;
use PostBoostClient\Model\FreeToolFormatCrossPostRequest;
$api = new FreeToolsApi(new GuzzleHttp\Client());
$result = $api->formatCrossPost(new FreeToolFormatCrossPostRequest(['text' => "Our spring menu is live, thanks @alice for the photos: https://example.com/menu", 'networks' => ["x", "mastodon", "linkedin"]]));
echo $result;
import (
"context"
"encoding/json"
"fmt"
postboost "github.com/postboost-co/postboost-go"
)
var request postboost.FreeToolFormatCrossPostRequest
if err := json.Unmarshal([]byte(`{"text":"Our spring menu is live, thanks @alice for the photos: https://example.com/menu","networks":["x","mastodon","linkedin"]}`), &request); err != nil {
panic(err)
}
client := postboost.NewAPIClient(postboost.NewConfiguration())
result, _, err := client.FreeToolsAPI.FormatCrossPost(context.Background()).FreeToolFormatCrossPostRequest(request).Execute()
fmt.Println(result, err)
require 'postboost'
api = PostBoost::FreeToolsApi.new
result = api.format_cross_post(PostBoost::FreeToolFormatCrossPostRequest.new({ text: "Our spring menu is live, thanks @alice for the photos: https://example.com/menu", networks: ["x", "mastodon", "linkedin"] }))
puts result.to_hash
import com.postboost.ApiClient;
import com.postboost.api.FreeToolsApi;
import com.postboost.model.FreeToolFormatCrossPostRequest;
import com.postboost.model.FreeToolFormatCrossPostResponse;
FreeToolsApi api = new FreeToolsApi(new ApiClient());
FreeToolFormatCrossPostRequest request = FreeToolFormatCrossPostRequest.fromJson("{\"text\":\"Our spring menu is live, thanks @alice for the photos: https://example.com/menu\",\"networks\":[\"x\",\"mastodon\",\"linkedin\"]}");
FreeToolFormatCrossPostResponse result = api.formatCrossPost(request);
System.out.println(result.toJson());
using Newtonsoft.Json;
using PostBoost.Client.Api;
using PostBoost.Client.Client;
using PostBoost.Client.Model;
var api = new FreeToolsApi(new Configuration());
var request = JsonConvert.DeserializeObject<FreeToolFormatCrossPostRequest>(@"{""text"":""Our spring menu is live, thanks @alice for the photos: https://example.com/menu"",""networks"":[""x"",""mastodon"",""linkedin""]}");
var result = await api.FormatCrossPostAsync(request);
Console.WriteLine(result.ToJson());
use postboost::apis::configuration::Configuration;
use postboost::apis::free_tools_api;
use postboost::models::FreeToolFormatCrossPostRequest;
let config = Configuration::new();
let request: FreeToolFormatCrossPostRequest = serde_json::from_str(r##"{"text":"Our spring menu is live, thanks @alice for the photos: https://example.com/menu","networks":["x","mastodon","linkedin"]}"##)?;
let result = free_tools_api::format_cross_post(&config, request).await?;
println!("{:?}", result);
echo '{"text":"Our spring menu is live, thanks @alice for the photos: https://example.com/menu","networks":["x","mastodon","linkedin"]}' | ./postboost-cli --content-type application/json formatCrossPost -
With a token, send Authorization: Bearer YOUR_API_TOKEN as a default header (how, per SDK).
Response
{
"networks": [
{
"key": "x",
"label": "X (Twitter) post",
"limit": 280,
"count": 78,
"fits": true,
"over_by": 0,
"links": 1,
"warnings": [
{
"code": "mentions_not_portable",
"message": "@handles are per network: check each one exists on X (Twitter)."
}
],
"thread": null
},
{
"key": "mastodon",
"label": "Mastodon post",
"limit": 500,
"count": 78,
"fits": true,
"over_by": 0,
"links": 1,
"warnings": [
{
"code": "mentions_not_portable",
"message": "@handles are per network: check each one exists on Mastodon. Use @user@server for people on other servers."
}
],
"thread": null
},
{
"key": "linkedin",
"label": "LinkedIn post",
"limit": 3000,
"count": 79,
"fits": true,
"over_by": 0,
"links": 1,
"warnings": [
{
"code": "mentions_not_portable",
"message": "@handles are per network: check each one exists on LinkedIn."
}
],
"thread": null
}
]
}
With MCP
Connect https://postboost.co/mcp/tools (setup) and ask, for example: Format one post for X, Threads, Bluesky, Mastodon and LinkedIn with the PostBoost format-cross-post tool.
Errors
| Status | When |
|---|---|
401 | The Authorization header holds an invalid token. Leave it out to call as a guest. |
413 | The JSON body is larger than 128 KB. |
422 | A field is invalid; the body lists the errors per field. |
429 | A limit is reached; see limits. |