Posts API Reference
The Posts API allows you to create, retrieve, and delete social media posts across multiple platforms.
Endpoints
Section titled “Endpoints”| Method | Endpoint | Description |
|---|---|---|
GET | /api/posts | List all posts |
GET | /api/posts/:id | Get a single post |
POST | /api/posts | Create a new post |
POST | /api/posts/:id/publish | Publish a draft post |
DELETE | /api/posts/:id | Delete a post |
List posts
Section titled “List posts”GET /api/posts
Retrieves a paginated list of all posts in the current profile group.
Query parameters
Section titled “Query parameters”| Name | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 0 | Page number (zero-indexed) |
per_page | integer | No | 10 | Number of posts per page |
profile_group_id | string | No | - | Filter by profile group (hashid) |
status | string | No | - | Filter by status: draft, scheduled, published, failed |
platforms | array | No | - | Array of platforms (e.g., platforms[]=instagram&platforms[]=tiktok) |
scheduled_after | string | No | - | ISO 8601 date to filter posts scheduled after that date |
Example
Section titled “Example”curl -X GET "https://api.postproxy.dev/api/posts?page=0&per_page=10" \ -H "Authorization: Bearer YOUR_API_KEY"import requests
response = requests.get( "https://api.postproxy.dev/api/posts", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"page": 0, "per_page": 10})
print(response.json())require 'net/http'require 'json'
uri = URI("https://api.postproxy.dev/api/posts?page=0&per_page=10")request = Net::HTTP::Get.new(uri)request["Authorization"] = "Bearer YOUR_API_KEY"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request)end
puts JSON.parse(response.body)const response = await fetch( "https://api.postproxy.dev/api/posts?page=0&per_page=10", { headers: { "Authorization": "Bearer YOUR_API_KEY" } });
const data = await response.json();console.log(data);Response:
{ "total": 42, "page": 0, "per_page": 10, "data": [ { "id": "abc123xyz", "body": "Check out our latest update!", "status": "processed", "scheduled_at": null, "created_at": "2024-01-15T10:30:00.000Z", "platforms": [ { "platform": "twitter", "status": "published", "params": null, "error": null, "attempted_at": "2024-01-15T10:30:01.000Z", "insights": { "impressions": 1523, "on": "2024-01-15T18:00:00.000Z" } }, { "platform": "instagram", "status": "published", "params": { "format": "post", "first_comment": "Link in bio!" }, "error": null, "attempted_at": "2024-01-15T10:30:02.000Z", "insights": { "impressions": 3842, "on": "2024-01-15T18:00:00.000Z" } } ] } ]}Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
total | integer | Total number of posts |
page | integer | Current page number |
per_page | integer | Items per page |
data | array | Array of post objects |
Get post
Section titled “Get post”GET /api/posts/:id
Retrieves a single post by its ID.
Path parameters
Section titled “Path parameters”| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Post hashid |
Example
Section titled “Example”curl -X GET "https://api.postproxy.dev/api/posts/abc123xyz" \ -H "Authorization: Bearer YOUR_API_KEY"import requests
response = requests.get( "https://api.postproxy.dev/api/posts/abc123xyz", headers={"Authorization": "Bearer YOUR_API_KEY"})
print(response.json())require 'net/http'require 'json'
uri = URI("https://api.postproxy.dev/api/posts/abc123xyz")request = Net::HTTP::Get.new(uri)request["Authorization"] = "Bearer YOUR_API_KEY"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request)end
puts JSON.parse(response.body)const response = await fetch( "https://api.postproxy.dev/api/posts/abc123xyz", { headers: { "Authorization": "Bearer YOUR_API_KEY" } });
const data = await response.json();console.log(data);Response:
{ "id": "abc123xyz", "body": "Check out our latest update!", "status": "processed", "scheduled_at": null, "created_at": "2024-01-15T10:30:00.000Z", "platforms": [ { "platform": "twitter", "status": "published", "params": null, "error": null, "attempted_at": "2024-01-15T10:30:01.000Z", "insights": { "impressions": 1523, "on": "2024-01-15T18:00:00.000Z" } } ]}Response fields
Section titled “Response fields”| Field | Type | Description |
|---|---|---|
id | string | Unique post identifier (hashid) |
body | string | Post body/text content |
status | string | Post status: processing, processed, scheduled |
scheduled_at | string|null | ISO 8601 timestamp if scheduled, null otherwise |
created_at | string | ISO 8601 timestamp of creation |
platforms | array | Array of platform-specific posting results |
Platform object fields
Section titled “Platform object fields”| Field | Type | Description |
|---|---|---|
platform | string | Platform identifier: facebook, instagram, tiktok, linkedin, youtube, twitter, threads |
status | string | Platform posting status: processing, published, failed, deleted |
params | object|null | Platform-specific parameters used for this post |
attempted_at | string|null | ISO 8601 timestamp of posting attempt |
insights | object | Engagement metrics (when available) |
insights.impressions | integer | Number of impressions/views |
insights.on | string | ISO 8601 timestamp when insights were captured |
Create post
Section titled “Create post”POST /api/posts
Creates a new post and publishes it to the specified platforms.
Request body
Section titled “Request body”| Name | Type | Required | Description |
|---|---|---|---|
post[body] | string | No* | Text content of the post |
post[scheduled_at] | string | No | ISO 8601 timestamp to schedule the post |
draft | boolean | No | If true, creates a draft that won’t publish until reviewed |
profiles | array | Yes | Array of profile IDs or platform names |
media | array | No* | Array of media URLs or file uploads |
platforms | object | No | Platform-specific parameters |
*Some platforms require media (Instagram, TikTok, YouTube). Some platforms require text content.
Draft posts
Section titled “Draft posts”Set draft: true to create a post that won’t be published automatically. Draft posts can be reviewed and then published using the Publish endpoint.
{ "post": { "body": "Content to review before posting" }, "profiles": ["instagram"], "draft": true}Profiles parameter
Section titled “Profiles parameter”The profiles array accepts either:
- Platform names:
"twitter","instagram","facebook", etc. - Uses the first connected profile for that platform - Profile IDs: Hashid of a specific profile
Media parameter
Section titled “Media parameter”You can provide media in two ways:
Option 1: URLs (JSON request)
Pass URLs to images or videos that PostProxy will download:
{ "media": [ "https://example.com/image1.jpg", "https://example.com/image2.png" ]}Option 2: File upload (multipart form)
Upload files directly using multipart/form-data:
curl -X POST "https://api.postproxy.dev/api/posts" \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "post[body]=Check out this photo!" \ -F "profiles[]=instagram" \ -F "profiles[]=facebook" \ -F "media[]=@/path/to/image.jpg"import requests
with open("/path/to/image.jpg", "rb") as f: response = requests.post( "https://api.postproxy.dev/api/posts", headers={"Authorization": "Bearer YOUR_API_KEY"}, data={ "post[body]": "Check out this photo!", "profiles[]": ["instagram", "facebook"] }, files={"media[]": f} )
print(response.json())require 'net/http'require 'uri'
uri = URI("https://api.postproxy.dev/api/posts")form_data = [ ["post[body]", "Check out this photo!"], ["profiles[]", "instagram"], ["profiles[]", "facebook"], ["media[]", File.open("/path/to/image.jpg")]]
request = Net::HTTP::Post.new(uri)request["Authorization"] = "Bearer YOUR_API_KEY"request.set_form(form_data, "multipart/form-data")
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request)end
puts response.bodyconst formData = new FormData();formData.append("post[body]", "Check out this photo!");formData.append("profiles[]", "instagram");formData.append("profiles[]", "facebook");formData.append("media[]", fileInput.files[0]);
const response = await fetch("https://api.postproxy.dev/api/posts", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY" }, body: formData});
const data = await response.json();console.log(data);When using file upload, use form field names with brackets: post[body], profiles[], media[].
Platform-specific parameters
Section titled “Platform-specific parameters”Pass platform-specific options in the platforms object. See Platform Parameters for all available options.
{ "platforms": { "instagram": { "format": "reel", "first_comment": "Check the link in bio!" }, "youtube": { "title": "My Video Title", "privacy_status": "public" } }}Example
Section titled “Example”curl -X POST "https://api.postproxy.dev/api/posts" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "post": { "body": "Hello from the API!" }, "profiles": ["twitter", "linkedin", "threads"], "media": ["https://example.com/image.jpg"] }'import requests
response = requests.post( "https://api.postproxy.dev/api/posts", headers={ "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, json={ "post": { "body": "Hello from the API!" }, "profiles": ["twitter", "linkedin", "threads"], "media": ["https://example.com/image.jpg"] })
print(response.json())require 'net/http'require 'json'
uri = URI("https://api.postproxy.dev/api/posts")request = Net::HTTP::Post.new(uri)request["Authorization"] = "Bearer YOUR_API_KEY"request["Content-Type"] = "application/json"request.body = { post: { body: "Hello from the API!" }, profiles: ["twitter", "linkedin", "threads"], media: ["https://example.com/image.jpg"]}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request)end
puts JSON.parse(response.body)const response = await fetch("https://api.postproxy.dev/api/posts", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ post: { body: "Hello from the API!" }, profiles: ["twitter", "linkedin", "threads"], media: ["https://example.com/image.jpg"] })});
const data = await response.json();console.log(data);Response (201 Created):
{ "id": "xyz789abc", "body": "Hello from the API!", "status": "processed", "scheduled_at": null, "created_at": "2024-01-15T10:30:00.000Z", "platforms": [ { "platform": "twitter", "status": "pending", "error": null, "params": null, "attempted_at": null }, { "platform": "linkedin", "status": "pending", "error": null, "params": null, "attempted_at": null }, { "platform": "threads", "status": "pending", "error": null, "params": null, "attempted_at": null } ]}Error responses
Section titled “Error responses”Missing profiles parameter (400):
{ "status": 400, "error": "Bad Request", "message": "param is missing or the value is empty: Missing profiles parameter"}Validation errors (422):
{ "errors": [ "Post profiles must have at least one profile selected", "Media is required for feed post on Instagram" ]}Delete post
Section titled “Delete post”DELETE /api/posts/:id
Deletes a post from the database. Note: This does not remove the post from social media platforms.
Path parameters
Section titled “Path parameters”| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Post hashid |
Example
Section titled “Example”curl -X DELETE "https://api.postproxy.dev/api/posts/abc123xyz" \ -H "Authorization: Bearer YOUR_API_KEY"import requests
response = requests.delete( "https://api.postproxy.dev/api/posts/abc123xyz", headers={"Authorization": "Bearer YOUR_API_KEY"})
print(response.json())require 'net/http'require 'json'
uri = URI("https://api.postproxy.dev/api/posts/abc123xyz")request = Net::HTTP::Delete.new(uri)request["Authorization"] = "Bearer YOUR_API_KEY"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request)end
puts JSON.parse(response.body)const response = await fetch( "https://api.postproxy.dev/api/posts/abc123xyz", { method: "DELETE", headers: { "Authorization": "Bearer YOUR_API_KEY" } });
const data = await response.json();console.log(data);Response:
{ "deleted": true}Publish post
Section titled “Publish post”POST /api/posts/:id/publish
Publishes a draft post. Only posts with status: "draft" can be published using this endpoint.
Path parameters
Section titled “Path parameters”| Name | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Post hashid |
Example
Section titled “Example”curl -X POST "https://api.postproxy.dev/api/posts/abc123xyz/publish" \ -H "Authorization: Bearer YOUR_API_KEY"import requests
response = requests.post( "https://api.postproxy.dev/api/posts/abc123xyz/publish", headers={"Authorization": "Bearer YOUR_API_KEY"})
print(response.json())require 'net/http'require 'json'
uri = URI("https://api.postproxy.dev/api/posts/abc123xyz/publish")request = Net::HTTP::Post.new(uri)request["Authorization"] = "Bearer YOUR_API_KEY"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request)end
puts JSON.parse(response.body)const response = await fetch( "https://api.postproxy.dev/api/posts/abc123xyz/publish", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY" } });
const data = await response.json();console.log(data);Response:
{ "id": "abc123xyz", "content": "Hello World!", "status": "processing", "scheduled_at": null, "created_at": "2024-01-15T10:30:00.000Z", "platforms": [ { "platform": "instagram", "status": "processing", "params": { "format": "post" }, "attempted_at": null } ]}Error responses
Section titled “Error responses”Post not found (404):
{ "error": "Not found"}Post is not a draft (422):
{ "error": "Post is not a draft"}Post statuses
Section titled “Post statuses”Post-level status
Section titled “Post-level status”| Status | Description |
|---|---|
draft | Post is saved but not published, awaiting review |
processing | Post is being published to platforms |
processed | All platform publishing attempts completed |
scheduled | Post is scheduled for future publishing |
Platform-level status
Section titled “Platform-level status”| Status | Description |
|---|---|
processing | Currently being published to this platform |
published | Successfully published |
failed | Publishing failed (check error message) |
deleted | Post was deleted on a platform |
Insights
Section titled “Insights”Insights (impressions/views) are collected periodically after a post is published. The insights object in the platform response contains:
| Field | Description |
|---|---|
impressions | Number of views/impressions on the platform |
on | Timestamp when the metrics were captured |
Insights are updated approximately every 8 hours for published posts.