Documentation menu

REST API reference

The TimeToPost REST API is the same API the web dashboard uses β€” everything you can click, you can script. All requests are JSON over HTTPS against https://timetopost.co/api, scoped to your active organization, and subject to the same plan limits and validation as the dashboard.

Authentication

Create a personal API token in the dashboard under Settings β†’ API. Tokens look like ttp_ followed by 48 hex characters, can optionally expire after 1–365 days, and are shown exactly once at creation β€” only a hash is stored, so copy it immediately. Send it as a Bearer token on every request:

Authorization: Bearer ttp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Two safety properties to know: a token acts with your full account permissions, and β€” deliberately β€” API tokens cannot create or revoke other tokens. Token management is browser-session only, so a leaked token can never mint replacements. Revoke tokens any time from the same Settings β†’ API page.

Posts

GET/api/posts

Lists all posts in your active organization, newest first. Each post includes id, content, platforms, status (lowercase: draft, scheduled, publishing, published, failed, partial), scheduledAt, publishedAt and mediaUrls.

curl
curl https://timetopost.co/api/posts \
  -H "Authorization: Bearer ttp_your_token_here"

# { "success": true, "posts": [ { "id": "...", "status": "scheduled", ... } ] }

POST/api/posts

Creates a post. Target accounts either by accountIds (specific connected accounts β€” integration ids from GET /api/integrations) or by platforms (e.g. ["instagram", "twitter"]). scheduledAt must be a valid ISO 8601 timestamp in the future; requests with a past time are rejected with a validation error. Omit it to save a draft. Returns 201 with the created post.

curl
curl -X POST https://timetopost.co/api/posts \
  -H "Authorization: Bearer ttp_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Launch day! πŸš€",
    "accountIds": ["cmb8x2k4p0001..."],
    "mediaUrls": ["https://media.timetopost.co/uploads/launch.jpg"],
    "thread": ["Tweet 2 of your X thread…", "Tweet 3 β€” up to 24 parts, 280 chars each"],
    "scheduledAt": "2026-07-01T15:00:00.000Z"
  }'

Also available: GET /api/posts/:id (fetch one), DELETE /api/posts/:id (delete/cancel before it fires).

Analytics

GET/api/analytics/optimal-times

Returns your best posting times computed from your own engagement history. Optional ?platform= query parameter (e.g. instagram, tiktok, twitter) narrows the analysis to one platform. Requires a plan with the best-time-to-post feature.

curl
curl "https://timetopost.co/api/analytics/optimal-times?platform=instagram" \
  -H "Authorization: Bearer ttp_your_token_here"

# {
#   "success": true,
#   "recommendation": {
#     "bestHours": [ { "hour": 18, "score": 0.92 }, ... ],   // top 5
#     "bestDays":  [ { "day": "Tuesday", "score": 0.88 }, ... ], // top 3
#     "dataPoints": 64,
#     "message": "..."
#   }
# }

Related endpoints: GET /api/analytics/optimal-times/by-account (per connected account), GET /api/analytics/next-optimal-time (the next best slot from now), GET /api/analytics/weekly-schedule, and GET /api/analytics/engagement-summary for aggregate likes, comments, shares and views.

Media uploads

POST/api/media/presign

Media is uploaded directly to storage with a short-lived presigned URL β€” your file never proxies through the API and storage credentials never reach the client. Three steps: request a presigned URL, PUT the file to it, then use the returned publicUrl in a post’s mediaUrls.

curl
# 1. Request a presigned upload URL
curl -X POST https://timetopost.co/api/media/presign \
  -H "Authorization: Bearer ttp_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{ "filename": "launch.jpg", "contentType": "image/jpeg", "size": 482133 }'

# { "success": true, "key": "...", "uploadUrl": "https://...",
#   "publicUrl": "https://...", "expiresIn": 300 }

# 2. Upload the file
curl -X PUT "<uploadUrl>" -H "Content-Type: image/jpeg" --data-binary @launch.jpg

# 3. Reference publicUrl in POST /api/posts mediaUrls

The body requires filename, contentType and size; uploads are validated for type and size before a URL is issued.

Errors

Errors use conventional HTTP status codes β€” 400 validation, 401 missing/invalid token, 403 plan or permission limits, 404 not found (including posts owned by other organizations) β€” with a JSON body containing success: false and a message.

Prefer working from an AI agent instead of raw HTTP? The MCP server wraps these endpoints as tools for Claude, Cursor and friends.