Endpoint and authentication
Use the existing direct content publishing endpoint. Authenticate with X-API-Key (server-side only) or a Bearer session. The accountId must belong to the authenticated tenant and must be an active Threads account.
POST /api/content/post
Request body
Set platform to threads, put the reply in content, and put the target post media ID in replyToId. The replyToId is the mediaId from keyword search. Do not put the URL from the search result in replyToId. Omit mediaItems for a text-only reply, or add mediaItems to reply with a photo or video using the same fields as a normal Threads post.
{
"platform": "threads",
"accountId": "YOUR_CONNECTED_THREADS_ACCOUNT_ID",
"mediaType": "text",
"content": "That is a useful point. I have seen the same result when I tried it.",
"replyToId": "18000000000000000"
}
Reply with a photo or video
replyToId only sets the reply target. The reply body follows the normal Threads post rules, so it can carry media. Send mediaItems with the reply text in content.
- Photo reply: mediaItems with one or more image URLs (.jpg, .jpeg, .png, .webp, .gif).
- Video reply: mediaItems with exactly one video URL (.mp4, .mov, .webm, .m4v, .avi).
- Do not mix photos and videos in one reply.
- content stays limited to 500 characters. content is required for a text-only reply and optional when mediaItems is present.
curl -X POST "https://api.wahdx.com/api/content/post" \
-H "X-API-Key: $WAHDX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "threads",
"accountId": "YOUR_CONNECTED_THREADS_ACCOUNT_ID",
"content": "Here is the screenshot you asked for.",
"mediaItems": [{ "url": "https://your-domain.com/reply-photo.jpg" }],
"replyToId": "18000000000000000"
}'
Example request
Keep the API key in a trusted backend. The reply text and target media ID stay in the request body.
curl -X POST "https://api.wahdx.com/api/content/post" \
-H "X-API-Key: $WAHDX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "threads",
"accountId": "YOUR_CONNECTED_THREADS_ACCOUNT_ID",
"mediaType": "text",
"content": "That is a useful point. I have seen the same result when I tried it.",
"replyToId": "18000000000000000"
}'
Response
On success, the response returns the published reply media ID and permalink when Threads provides one.
{
"success": true,
"accountId": "YOUR_CONNECTED_THREADS_ACCOUNT_ID",
"platform": "threads",
"status": "PUBLISH_COMPLETE",
"data": {
"id": "18000000000000001",
"publish_id": "18000000000000001",
"public_post_url": "https://www.threads.com/@youraccount/post/example"
},
"public_post_url": "https://www.threads.com/@youraccount/post/example"
}
Requirements and safety
The target is a media ID, not a permalink. The API replies through the connected account and does not reuse the access token or provider URL supplied by the caller.
- replyToId is supported only when platform is threads. Other platforms receive a 400 response.
- replyToId must be an opaque provider media ID of 1 to 128 ASCII letters, digits, underscores, or hyphens.
- The publishing account is loaded by accountId within the authenticated tenant. A user cannot use another tenant’s account.
- threads_manage_replies permission is required to publish a reply. Missing permission does not disable normal publishing.
- The reply text uses the normal Threads text limit of 500 characters. content is required for a text-only reply and optional when mediaItems is present.
- A media reply follows the normal Threads post media rules: one or more photos, or exactly one video, never mixed.
- If you want the target selected by a person, show the search result text and permalink before asking them to submit the reply.
How this fits keyword search
Keyword search finds candidates, but it does not post a reply. Use the result’s mediaId as replyToId in this endpoint. This direct API call does not create a reply rule or auto-reply event; it publishes the requested reply once.
// 1. Read results from GET /api/engagement/keywords/search
// 2. After the operator picks a result, send:
{
"platform": "threads",
"accountId": "YOUR_CONNECTED_THREADS_ACCOUNT_ID",
"mediaType": "text",
"content": "Your reply text",
"replyToId": "<selected result.mediaId>"
}