How-to Guide

Automate Social Media Posting with Python

Quick Answer: Use Python's requests library with the documented DOHOO REST API: request a presigned upload URL, PUT the original file bytes to S3, wait for processing, list your social connections, and call the relevant immediate-publish endpoint with the returned fileId. REST API access requires Business or Agency.

The safest automation starts from the public contract that is actually documented. The example below publishes one uploaded video to Instagram and can be extended to the other platform-specific endpoints.

Prerequisites

  • Python 3.10+ and requests
  • A DOHOO Business or Agency subscription
  • An API key stored in DOHOO_API_KEY
  • At least one connected social account

A Verified Python Client

import os, time, mimetypes, requests
from pathlib import Path

BASE_URL = "https://dohoo.ai"
API_KEY = os.environ["DOHOO_API_KEY"]
HEADERS = {"X-API-Key": API_KEY}

def upload_file(path: str) -> str:
    file_path = Path(path)
    content_type = mimetypes.guess_type(file_path.name)[0] or "application/octet-stream"

    slot = requests.post(
        f"{BASE_URL}/api/upload/presigned-url",
        headers={**HEADERS, "Content-Type": "application/json"},
        json={"filename": file_path.name, "contentType": content_type},
        timeout=30,
    )
    slot.raise_for_status()
    data = slot.json()

    with file_path.open("rb") as source:
        put = requests.put(
            data["uploadUrl"],
            headers={"Content-Type": content_type},
            data=source,
            timeout=300,
        )
    put.raise_for_status()

    file_id = data["fileId"]
    for _ in range(120):
        status = requests.get(
            f"{BASE_URL}/api/upload/status/{file_id}",
            headers=HEADERS,
            timeout=30,
        )
        status.raise_for_status()
        payload = status.json()
        if payload.get("status") in {"completed", "ready"}:
            return file_id
        time.sleep(5)
    raise TimeoutError("Media processing did not complete in time")

def list_connections():
    response = requests.get(
        f"{BASE_URL}/api/connections/unified",
        headers=HEADERS,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()

def publish_instagram(file_id: str, connection_id: str, caption: str):
    response = requests.post(
        f"{BASE_URL}/api/v2/instagram/publish",
        headers={**HEADERS, "Content-Type": "application/json"},
        json={
            "connectionId": connection_id,
            "fileId": file_id,
            "caption": caption,
        },
        timeout=120,
    )
    response.raise_for_status()
    return response.json()

file_id = upload_file("video.mp4")
connections = list_connections()
instagram = next(c for c in connections if c["platform"] == "instagram")
result = publish_instagram(file_id, instagram["id"], "Published with DOHOO API")
print(result)

The status response schema should be checked against your live account before hard-coding an enum. The loop accepts both completed and ready because processing labels can differ between interfaces; log the full response while integrating.

What About Scheduling?

The current public REST reference documents immediate platform publish endpoints. DOHOO MCP exposes platform-specific scheduling tools with scheduledAt and an IANA timezone. Do not invent a REST schedule route: either use the documented MCP tools or wait until a REST scheduling endpoint is published in the reference.

Validation and Error Handling

  • Call raise_for_status() after every HTTP request.
  • Log the response body for 4xx and 5xx errors without logging your API key.
  • Retrieve connection IDs from /api/connections/unified instead of hard-coding them.
  • Keep platform limits in your validation layer: Instagram captions 2,200 characters, X text 280, LinkedIn text 3,000, YouTube title 100.

FAQ

Do I need a special SDK?

No. The documented REST API uses JSON over HTTPS and the X-API-Key header.

Can Python schedule posts?

Yes through an MCP client or another documented scheduler integration. The public REST reference should be your source of truth before you hard-code a schedule endpoint.

Can captions come from Google Sheets?

Yes. Read rows with the Google Sheets API or export CSV, then pass the approved values into the same publishing functions.

How should I store the API key?

Use an environment variable or a secrets manager. Never commit the key to source control.

Publish to all 8 platforms in one step — no silent failures.

View DOHOO plans