No libraries. No SDK. No nonsense.
I needed to post to Mastodon programmatically. Every guide I found involved installing a Ruby gem, a Python library, or some Node.js package with 47 transitive dependencies.
Here's what actually works:
``bash
# Post a toot
curl -X POST "https://mstdn.social/api/v1/statuses" \
-H "Authorization: Bearer $MASTODON_TOKEN" \
-F "status=Hello from the command line" \
-F "visibility=public"
`
That's it. Mastodon's API is REST. It speaks HTTP.
curl speaks HTTP. Done.
The 20-Line Automation
`bash
#!/bin/bash
# post-toot.sh — Post to Mastodon from the terminal
# Usage: ./post-toot.sh "Your toot text here"
INSTANCE="${MASTODON_INSTANCE:-mstdn.social}"
TOKEN="$MASTODON_TOKEN"
if [ -z "$TOKEN" ]; then
echo "Error: Set MASTODON_TOKEN environment variable"
exit 1
fi
if [ -z "$1" ]; then
echo "Usage: $0 "
exit 1
fi
STATUS="$1"
RESPONSE=$(curl -s -X POST "https://$INSTANCE/api/v1/statuses" \
-H "Authorization: Bearer $TOKEN" \
-F "status=$STATUS" \
-F "visibility=public")
URL=$(echo "$RESPONSE" | python3 -c "import json,sys; print(json.load(sys.stdin).get('url','ERROR'))")
echo "Posted: $URL"
`
Getting the Token
Create an OAuth app: POST /api/v1/apps
Authorize it in your browser: GET /oauth/authorize
Exchange the code: POST /oauth/token
Three HTTP calls. No SDK required.
What Else Can You Do?
`bash
# Upload an image
curl -X POST "https://$INSTANCE/api/v2/media" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@screenshot.png"
# Schedule a post
curl -X POST "https://$INSTANCE/api/v1/statuses" \
-H "Authorization: Bearer $TOKEN" \
-F "status=Scheduled post" \
-F "scheduled_at=2026-04-26T09:00:00Z"
# Search the fediverse
curl "https://$INSTANCE/api/v2/search?q=python+devops&type=accounts" \
-H "Authorization: Bearer $TOKEN"
``
The entire Mastodon API is accessible via plain HTTP. No vendor lock-in, no dependency hell, no version conflicts. This is how APIs should work.
The fediverse is growing. Knowing how to interact with it programmatically — without a framework — is a useful skill. And it takes 20 lines of bash, not 20 dependencies.