A post request normally waits for the networks to finish, up to 59 seconds. Big videos and slow networks can take longer, and your HTTP client may give up first. Send async_upload=true and Reelspan answers straight away with a request_id; the post carries on in the background and you read the outcome later.
curl -X POST https://api.reelspan.com/v1/posts/video \
-H "Authorization: Bearer $REELSPAN_API_KEY" \
-F "user=my-brand" \
-F "platform[]=tiktok" \
-F "platform[]=youtube" \
-F "title=Launch day" \
-F "async_upload=true" \
-F "[email protected]"import { Reelspan } from 'reelspan';
import { readFile } from 'node:fs/promises';
const reelspan = new Reelspan();
const post = await reelspan.posts.video({
user: 'my-brand',
platforms: ['tiktok', 'youtube'],
title: 'Launch day',
video: { data: await readFile('launch.mp4'), name: 'launch.mp4', type: 'video/mp4' },
async: true,
});
const status = await reelspan.posts.wait(post.request_id);from reelspan import Reelspan
reelspan = Reelspan()
post = reelspan.posts.video("my-brand", ["tiktok", "youtube"], "launch.mp4", "Launch day", async_upload=True)
status = reelspan.posts.wait(post["request_id"])What comes back
An async post answers 200 with the request's id and how many networks it went to:
{
"success": true,
"message": "Upload initiated successfully in background.",
"request_id": "9b1f6c2e8a3d4f50b7e1c9a2d6f3e8b1",
"total_platforms": 2
}The same shape comes back when you did not ask for async but the networks were still working after 59 seconds: the request moves to the background on its own, and nothing is lost.
Check for
resultsin the body rather than for a status code. A post that finished in time hasresultskeyed by network; a post still running hasmessageandtotal_platformsinstead. If every network has already finished by the time Reelspan answers, an async request also returnsresults.
Requests that are checked and refused (a missing field, an unknown profile, a file over your plan's size) still fail at once with an HTTP error, async or not. See Errors.
Following the post
Poll the status
GET /v1/posts/status?request_id=… returns the overall status and one entry in results per network that has finished. Networks still working are not listed yet; completed and total tell you how far it got.
curl "https://api.reelspan.com/v1/posts/status?request_id=9b1f6c2e8a3d4f50b7e1c9a2d6f3e8b1" \
-H "Authorization: Bearer $REELSPAN_API_KEY"const status = await reelspan.posts.status({ requestId: '9b1f6c2e8a3d4f50b7e1c9a2d6f3e8b1' });status = reelspan.posts.status(request_id="9b1f6c2e8a3d4f50b7e1c9a2d6f3e8b1")status is one of:
| Status | Meaning |
|---|---|
pending |
Accepted, nothing has finished yet (also a scheduled post waiting for its time). |
in_progress |
At least one network is working or has finished; others are still going. |
completed |
Every network finished and at least one published. Check each result: some may have failed. |
failed |
Every network finished and none published. |
cancelled |
A scheduled post that was cancelled. |
The full response is on Post status.
How often to poll
Poll every 5 seconds or more. Each status call counts against your rate limit, the same as any other request. A sensible pattern is to wait 5 seconds, then back off towards 15 to 30 seconds for large videos, which can take minutes on networks that process video after upload.
The SDKs' wait helpers poll for you until the status is completed, failed or cancelled, or a timeout passes (10 minutes by default). They poll every 3 seconds unless you set intervalMs (Node) or interval (Python); raise it if you run many posts at once.
const status = await reelspan.posts.wait(requestId, { intervalMs: 10_000, timeoutMs: 900_000 });status = reelspan.posts.wait(request_id, timeout=900, interval=10)Or receive a webhook
Instead of polling, register a webhook and Reelspan sends an upload_completed event for each network as it finishes, with that network's success, url, post_id, error and error_code, plus your request_id, job_id and external_id. A post to three networks sends three events. See Webhooks.
Send your own
request_id(8 to 100 letters, digits,_or-) with the post. You know the id before the response arrives, so you can poll it even if the connection drops mid-request. Anexternal_idcomes back in status, history and webhooks too, for matching posts to your own records.
Scheduled posts use job_id
A post with scheduled_date or add_to_queue=true answers 202 with both a job_id and a request_id, and does not publish until its time. You can read its status with either id:
curl "https://api.reelspan.com/v1/posts/status?job_id=sched_3Jd9aQ" \
-H "Authorization: Bearer $REELSPAN_API_KEY"const status = await reelspan.posts.status({ jobId: 'sched_3Jd9aQ' });status = reelspan.posts.status(job_id="sched_3Jd9aQ")Until it runs, its status is pending. Use the job_id to edit or cancel it; see Scheduling and repeats.
When a network fails
One network failing never fails the others. Temporary errors on the network's side (timeouts, its own rate limits, 5xx answers) are retried automatically, up to four attempts with growing pauses, before the result is final. A final failure carries an error_code: look it up in Errors or Troubleshooting, then send only the failed networks again with Retry.