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 API tokens deliberately 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.