PostFast API
Programmatically schedule and publish posts across 11 social platforms, upload media, and read analytics. REST over HTTPS, authenticated with a single workspace API key.
pf-api-keyQuickstart: a 200 in under 2 minutes
- Generate a workspace API key from Workspace Settings (requires an ADMIN role).
- Send it in the
pf-api-keyheader. - Make a cheap read to confirm it works: list your connected accounts.
curl -X GET "https://api.postfa.st/social-media/my-social-accounts" \
-H "pf-api-key: YOUR_WORKSPACE_API_KEY"To try the API without writing code, fork the PostFast API collection on Postman and paste your key into its pf_api_key variable.
API Endpoints
I. Authentication
Overview
All API requests must be authenticated using an API key specific to your workspace. The API key must be included in the request headers as pf-api-key.
Generating an API Key
Users with an ADMIN role in a workspace can generate an API key from the Workspace Settings page within the PostFast web application. Each API key is uniquely tied to a single workspace and grants access only to the social media accounts connected within that specific workspace. This key is then used for authenticating your REST API requests.
Example Header:
pf-api-key: YOUR_WORKSPACE_API_KEYRate Limiting
Rate limits are counted per endpoint, per workspace API key. Calls to one endpoint never use another endpoint's budget, so reaching the limit on one endpoint does not slow down the others.
Every endpoint has four windows: 1 minute, 5 minutes, 1 hour, and 24 hours. Exceeding any of them returns a 429. Each endpoint page lists the windows that endpoint sets itself; any window it does not set uses the default below.
Default Limits (Per Endpoint)
72 requests per minute180 requests per 5 minutes360 requests per hour2,400 requests per day
For example, DELETE /social-posts/:id sets 200 requests per hour, so it allows 2,400 requests per day, 200 per hour, 180 per 5 minutes, 72 per minute.
How the Windows Work
- A window starts at the endpoint's first call, not on a clock boundary. The 24-hour window is not a reset at midnight UTC.
- Once a window is exceeded, that endpoint stays blocked for the full length of the window from that moment: up to 60 seconds for the minute window and up to 24 hours for the daily one.
- Calls made while blocked still count toward the window, so retrying early can keep the endpoint blocked.
Rate Limit Headers
Every response carries one set of headers per window, named short (1 minute), medium (5 minutes), long (1 hour), and daily (24 hours). The first call to an endpoint on the default minute and 5-minute limits returns, among others:
X-RateLimit-Limit-short: 72
X-RateLimit-Remaining-short: 71
X-RateLimit-Reset-short: 60
X-RateLimit-Limit-medium: 180
X-RateLimit-Remaining-medium: 179
X-RateLimit-Reset-medium: 300Header meanings:
X-RateLimit-Limit-[window]: The endpoint's limit for that windowX-RateLimit-Remaining-[window]: Requests left in the windowX-RateLimit-Reset-[window]: Seconds until the window resets
Rate Limit Exceeded (429 Response)
When a window is exceeded, the response carries a retry header named after that window, plus the standard Retry-After with the same value:
Retry-After-long: 2395
Retry-After: 2395{
"statusCode": 429,
"message": "Too many requests. Please try again later.",
"error": "Too Many Requests"
}Retry-After: Seconds to wait before calling this endpoint again, up to 60 for the minute window and up to 86,400 for the daily one. This is the standard header, and the one to read if your HTTP client, n8n or Zapier handles back-off for you.Retry-After-[window]: The same value, named after the window that was exceeded (for exampleRetry-After-long). Useful for telling which limit you hit.
Staying Inside the Limits
- Read the
X-RateLimit-Remaining-[window]headers and slow down before one reaches 0. - On a 429, wait
Retry-Afterseconds before calling that endpoint again. Retrying earlier still counts toward the window. - Don't poll the account list or the post list in a tight loop.
Error Responses
Common HTTP status codes you might encounter:
- 400 Bad Request - The request was malformed (e.g., missing required fields, invalid JSON). Check the response body for specific error messages. Also returned when scheduling a post to a social account that is currently
DISABLED(revoked/expired token or suspended account); reconnect it in the PostFast app first. - 401 Unauthorized - The API key is missing, invalid, or not authorized for the workspace.
- 403 Forbidden - The API key is valid, but does not have permissions for the requested action (e.g., trying to access resources of another workspace).
- 404 Not Found - The requested resource could not be found (e.g.,
tiktokSounds.socialMediaNotFoundwhen the account is not a TikTok account in your workspace). Deleting a post never returns 404: an unknown id answers 200 with{ "deleted": false }. - 429 Too Many Requests - You have exceeded the rate limit for the endpoint.
- 500 Internal Server Error - An unexpected error occurred on our server.
III. Typical Workflow: Scheduling Posts with Media
- Authentication: Ensure you have a valid
pf-api-keyfor your workspace. - (Optional) Identify Target Account: Call
GET /social-media/my-social-accountsto list available social media accounts and retrieve theidof the account you want to post to. Store these IDs as they are generally stable. - Request Signed URLs for Media: If your posts include media:
- Call
POST /file/get-signed-upload-urlswith thecontentType(e.g.,image/png) andcount. - Receive a response containing an array of
{ key, signedUrl }objects.
- Call
- Upload Media to S3: For each media item:
- Perform an HTTP
PUTrequest to thesignedUrl. - The request body must be the raw file data.
- The
Content-Typeheader of this PUT request must match thecontentTypeused in the previous step.
// Upload file to S3 using the signed URL from previous step const fs = require('fs'); const file = fs.readFileSync('/path/to/your/image.png'); const response = await fetch(signedUrl, { method: 'PUT', body: file, headers: { 'Content-Type': 'image/png' // Must match contentType from step 1 } }); if (response.ok) { // File uploaded successfully // Use the 'key' from step 1 in your social posts } - Perform an HTTP
- Create the Social Posts:
- Call
POST /social-posts. - In the request body, include an array of posts in the
postsfield, each containingcontent,scheduledAt, andsocialMediaId. - If media was uploaded, populate the
mediaItemsarray for each post using thekey(s) from step 3 (e.g.,image/a1b2c3d4-e5f6-7890-1234-567890abcdef.png). Ensure thetypefield ('IMAGE' or 'VIDEO') matches the key prefix. - Optionally include
controlsfor platform-specific settings.
- Call
Social Media Account Management
/social-media/my-social-accountsRetrieves a list of social media accounts connected to the workspace associated with the API key. Each account includes its latest daily follower or subscriber count.
/social-media/{socialMediaId}/follower-historyReturns daily follower/subscriber snapshots for one connected account, plus the current count and the net change over the range. Build growth charts without storing your own snapshots. The latest count is also on
GET /social-media/my-social-accounts./social-media/search-placesSearch real-world places (restaurants, venues, hotels, landmarks) to geotag on Facebook and Instagram posts. The returned
idworks as bothfacebookPlaceIdandinstagramLocationId./social-media/{socialMediaId}/pinterest-boardsRetrieves all Pinterest boards for a connected Pinterest account. Use the
boardIdfield when settingpinterestBoardIdon a Pinterest post./social-media/{socialMediaId}/youtube-playlistsRetrieves all YouTube playlists for a connected YouTube account. Use the
playlistIdfield when settingyoutubePlaylistIdon a YouTube post./social-media/{socialMediaId}/gbp-locationsReturns all synced Google Business Profile locations for a connected account. Use the
locationIdfield asgbpLocationIdwhen creating GBP posts./social-media/{socialMediaId}/tiktok-soundsReturns TikTok's trending, pre-cleared sounds for a connected TikTok account, ranked by a genre, country, and time window you choose. Use the
musicSoundIdfield astiktokMusicSoundIdwhen creating a TikTok photo carousel or video post./social-media/connect-linkGenerates a secure connect link that lets someone connect their social accounts to your workspace without a PostFast account. Can be scoped to specific platforms and return the user to your own app when done. Optionally emails the link.