Skip to main content

Manage Scheduled Posts

Schedule your uploads in advance and keep full control over them with our job management endpoints. This page covers how to list and cancel scheduled jobs created via the scheduled_date parameter.


List Scheduled Posts

EndpointGET /api/uploadposts/schedule
AuthenticationRequired. Either an Apikey (Authorization: Apikey <token>) or a white-label profile JWT (Authorization: Bearer <profile_jwt>).
Query ParamsAll optional — see below.

Query Parameters

ParamTypeDescription
profile_usernamestringReturn only the jobs of this profile.
fromstringISO-8601 lower bound on scheduled_date, inclusive.
tostringISO-8601 upper bound on scheduled_date, exclusive.
limitintegerPage size. Omit to return every matching job.
offsetintegerNumber of jobs to skip, ordered by scheduled_date ascending. Defaults to 0.

Malformed from / to / limit / offset values are ignored rather than rejected.

White-label profile JWTs are scoped automatically

When you authenticate with a profile JWT, results are restricted to that profile and the profile_username parameter is ignored. You cannot widen the scope past the profile the token was issued for.

curl "https://api.upload-post.com/api/uploadposts/schedule?profile_username=my_profile&from=2024-12-01T00:00:00Z&to=2025-01-01T00:00:00Z&limit=20" \
-H "Authorization: Apikey YOUR_API_KEY"

Success Response 200 OK

Returns an object containing the page of jobs plus its pagination metadata:

{
"scheduled_posts": [
{
"job_id": "a1b2c3d4e5f67890a1b2c3d4e5f67890",
"scheduled_date": "2024-12-25T10:30:00Z",
"post_type": "video",
"profile_username": "my_upload_post_profile",
"title": "Merry Christmas!",
"external_id": "clip-4821",
"source_filename": "christmas_cut_v3.mp4",
"platforms": ["tiktok", "instagram"],
"platform_content": {
"tiktok": { "title": "Merry Christmas!", "caption": "" },
"instagram": { "title": "Merry Christmas!", "caption": "Happy holidays" }
},
"has_preview": true,
"preview_url": null
}
],
"total": 42,
"limit": 20,
"offset": 0
}
FieldTypeDescription
scheduled_postsarrayThe requested page of scheduled-job objects.
totalintegerTotal number of jobs matching your filters, ignoring limit/offset. Use it to build a pager.
limitinteger | nullThe limit that was applied; null when you didn't send one.
offsetintegerThe offset that was applied.

Each element of scheduled_posts contains:

FieldTypeDescription
job_idstringUnique identifier of the scheduled job. Required to edit or cancel it.
scheduled_datestringISO-8601 date/time when the post will go live. Time is in UTC.
post_typestringOne of video, photo, text, or unknown.
profile_usernamestringUpload-Post profile that will publish the content.
titlestringText shown in a calendar. For single-platform jobs this is the text that platform will actually publish.
external_idstring | nullYour own identifier for this post, echoed back exactly as you sent it. See Correlating posts with your own system.
source_filenamestring | nullOriginal file name of the uploaded media, when the job was created from a file or a URL. null for text posts.
caption / descriptionstringGeneric caption and description stored with the job.
platformsarrayPlatforms the job will publish to.
platform_contentobjectPer-platform title / caption, falling back to the generic values.
fieldsobjectThe editable per-platform and global fields, as accepted by the PATCH endpoint.
has_coverbooleanWhether a cover image is stored for the job.
cover_preview_urlstring | nullPre-stored cover URL, when one exists.
has_previewbooleanWhether a previewable video/photo asset exists for the job.
preview_urlnullAlways null — media URLs are signed on demand, see below.
thumbnail_urlstring | nullStored thumbnail, when one exists.
original_timezonestring | nullTimezone the job was originally scheduled in.
original_scheduled_strstring | nullThe original scheduled datetime string as submitted.

Correlating posts with your own system

If you schedule from your own catalogue, you likely need to map a scheduled job back to the row it came from — to detect what you have already queued, or to show status next to your own records.

Do not match on title. It is editable, both through the PATCH endpoint and in the dashboard calendar, so a post that gets retitled stops matching and looks like it was never scheduled.

Send your own identifier as external_id when you create the post, and read it back here:

curl -X POST https://api.upload-post.com/api/upload \
-H "Authorization: ApiKey YOUR_API_KEY" \
-F "user=my_profile" \
-F "platform[]=tiktok" \
-F "title=Merry Christmas!" \
-F "scheduled_date=2024-12-25T10:30:00Z" \
-F "external_id=clip-4821" \
-F "video=@christmas_cut_v3.mp4"

external_id accepts any string up to 255 characters. It can also be sent as an X-External-Id header, which is handy when you cannot easily add form fields. It is available on /api/upload, /api/upload_photos and /api/upload_text, for both immediate and scheduled posts, and it is returned by Upload Status and Upload History as well as this endpoint.

external_id is a label, not a duplicate guard

Upload-Post stores and returns external_id but never enforces anything with it. Reusing one does not block a publish — that is deliberate, so a genuine repost of the same asset still goes out.

If you want a request to be suppressed when it is accidentally sent twice, that is a separate field: send an Idempotency-Key header, which collapses repeat requests for 24 hours. The two are independent and can be used together.

Media previews are fetched per job

Signing one URL per job made this endpoint time out for large schedules, so preview_url is no longer populated here. When has_preview is true, fetch the signed URL for that single job with GET /api/uploadposts/schedule/<job_id>/preview.

Error Responses

StatusReason
401 UnauthorizedMissing or invalid token.

Cancel a Scheduled Post

EndpointDELETE /api/uploadposts/schedule/<job_id>
AuthenticationRequired. Either an Apikey (Authorization: Apikey <token>) or a white-label profile JWT (Authorization: Bearer <profile_jwt>). When authenticated with a profile JWT, the job must belong to that profile and the profile must have readonly_calendar: false.
URL Paramjob_id — ID obtained from the list endpoint.

Success Response 200 OK

{
"success": true,
"message": "Job <job_id> cancelled and assets deleted."
}

Error Responses

StatusBodyCondition
401 Unauthorized Invalid or missing token.
404 Not Found{ "success": false, "error": "Job not found" }The supplied job_id does not exist or doesn't belong to the authenticated user.
500 Internal Server Error Unexpected failure while cancelling the job or deleting its assets.

Edit a Scheduled Post

EndpointPATCH /api/uploadposts/schedule/<job_id>
AuthenticationRequired. Either an Apikey (Authorization: Apikey <token>) or a white-label profile JWT (Authorization: Bearer <profile_jwt>). When authenticated with a profile JWT, the job must belong to that profile and the profile must have readonly_calendar: false.
URL Paramjob_id — ID obtained from the list endpoint.
BodyJSON object with one or more of the fields below.
FieldTypeRequiredDescription
scheduled_datestringNoISO-8601 date/time, e.g., "2025-10-05T10:30:00Z". Must be in the future and within 1 year. Interpreted as UTC unless timezone is provided.
timezonestringNoIANA timezone identifier (e.g., "Europe/Madrid", "America/New_York"). If provided, scheduled_date is interpreted in this timezone. Defaults to UTC if omitted. See IANA Time Zone Database.
titlestringNoNew post title/caption.
captionstringNoNew caption/description.

Success Response 200 OK

{
"success": true,
"job_id": "a1b2c3d4e5f67890a1b2c3d4e5f67890",
"scheduled_date": "2025-10-05T10:30:00Z",
"title": "Updated title",
"caption": "Updated caption"
}

Error Responses

StatusBodyCondition
400 Bad Request{ "success": false, "error": "<reason>" }Invalid body; invalid/past date; job not editable; daily limit reached.
401 Unauthorized Invalid or missing token.
403 Forbidden{ "success": false, "error": "Forbidden" }The job does not belong to the authenticated user, or the profile JWT does not match the job's profile.
403 Forbidden{ "success": false, "message": "This calendar is read-only…", "error_code": "READONLY_CALENDAR" }Authenticated with a profile JWT for a profile that has readonly_calendar: true.
404 Not Found{ "success": false, "error": "Job not found" }The supplied job_id does not exist.
500 Internal Server Error Unexpected failure while editing the job.

Example Request

curl -X PATCH "https://api.upload-post.com/api/uploadposts/schedule/JOB_ID" \
-H "Content-Type: application/json" \
-H "Authorization: Apikey <token>" \
-d '{
"scheduled_date": "2025-10-05T10:30:00",
"timezone": "Europe/Madrid",
"title": "Updated title",
"caption": "Updated caption"
}'

See Also