Post Logs
Get detailed publish attempt history for a post group. Useful for debugging failed posts and understanding the publish timeline.
Endpoint
GET https://api.postpost.dev/api/v1/post-logs/:postGroupIdHeaders
| Header | Required | Description |
|---|---|---|
x-api-key | Yes | Your API key |
x-postpost-user-id | No | Managed user ID (workspace only) |
x-postpost-client | No | Set to mcp for MCP tool access |
MCP access: If the
x-postpost-client: mcpheader is sent, the server validatesentitlements.features.mcpAccessand returns403 "MCP access is not enabled for this account"if the feature is not enabled.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
postGroupId | string | The post group ID |
Note: Results are limited to the first 100 log entries per post group (sorted ascending by creation time, oldest first).
Response
{
"success": true,
"logs": [
{
"_id": "65f8a1b2c3d4e5f6a7b8c9d0",
"postGroupId": "507f1f77bcf86cd799439011",
"postId": "507f1f77bcf86cd799439012",
"platform": "linkedin",
"event": "processing",
"createdAt": "2026-02-22T14:30:00.000Z"
},
{
"_id": "65f8a1b2c3d4e5f6a7b8c9d1",
"postGroupId": "507f1f77bcf86cd799439011",
"postId": "507f1f77bcf86cd799439012",
"platform": "linkedin",
"event": "publish_attempted",
"retryCount": 0,
"createdAt": "2026-02-22T14:30:01.000Z"
},
{
"_id": "65f8a1b2c3d4e5f6a7b8c9d2",
"postGroupId": "507f1f77bcf86cd799439011",
"postId": "507f1f77bcf86cd799439012",
"platform": "linkedin",
"event": "publish_succeeded",
"createdAt": "2026-02-22T14:30:03.000Z"
},
{
"_id": "65f8a1b2c3d4e5f6a7b8c9d3",
"postGroupId": "507f1f77bcf86cd799439011",
"event": "processing",
"createdAt": "2026-02-22T14:30:00.000Z"
},
{
"_id": "65f8a1b2c3d4e5f6a7b8c9d4",
"postGroupId": "507f1f77bcf86cd799439011",
"postId": "507f1f77bcf86cd799439013",
"platform": "threads",
"event": "publish_attempted",
"retryCount": 1,
"createdAt": "2026-02-22T14:30:01.000Z"
},
{
"_id": "65f8a1b2c3d4e5f6a7b8c9d5",
"postGroupId": "507f1f77bcf86cd799439011",
"postId": "507f1f77bcf86cd799439013",
"platform": "threads",
"event": "publish_failed",
"error": "Error validating access token",
"httpStatus": 401,
"retryCount": 1,
"metadata": {
"errorCode": "PLATFORM_AUTH_EXPIRED",
"retryable": false
},
"createdAt": "2026-02-22T14:30:02.000Z"
}
]
}Note: Response also includes
updatedAt(auto-managed by Mongoose) and__v(Mongoose version key) fields, omitted from examples for brevity.
Log Fields
| Field | Type | Description |
|---|---|---|
_id | string | Unique log entry ID |
postGroupId | string | Parent post group ID |
postId | string/undefined | Individual platform post ID. May be absent for group-level events (e.g., initial processing). |
platform | string/undefined | Platform name (twitter, linkedin, etc.). May be absent for group-level events. |
event | string | Event type (see table below) |
error | string or absent | Error message (for failed events). Absent from the response when there is no error (not null). |
httpStatus | number or absent | HTTP status code from platform. Absent from the response when not applicable (not null). |
retryCount | number or absent | Number of retry attempts. Absent if no retries have occurred -- do not assume it defaults to 0. |
metadata | object or absent | Additional event data. Absent from the response when there is no metadata (not null). |
createdAt | string | Event timestamp |
updatedAt | string | Last update timestamp (auto-managed by Mongoose) |
__v | number | Mongoose version key. Present in responses but not part of the documented schema — can be safely ignored. |
Event Types
| Event | Description |
|---|---|
scheduled | Post was scheduled |
processing | Post started processing |
publish_attempted | Publish request sent to platform |
publish_succeeded | Successfully published |
publish_failed | Publishing failed |
status_changed | Post status changed |
Examples
JavaScript (fetch)
const postGroupId = '507f1f77bcf86cd799439011';
const response = await fetch(
`https://api.postpost.dev/api/v1/post-logs/${postGroupId}`,
{ headers: { 'x-api-key': 'YOUR_API_KEY' } }
);
const { logs } = await response.json();
// Group logs by platform
const byPlatform = logs.reduce((acc, log) => {
if (!acc[log.platform]) acc[log.platform] = [];
acc[log.platform].push(log);
return acc;
}, {});
// Check for failures
const failures = logs.filter(l => l.event === 'publish_failed');
if (failures.length > 0) {
console.log('Failed platforms:');
failures.forEach(f => {
console.log(` ${f.platform}: ${f.error} (HTTP ${f.httpStatus})`);
});
}Python (requests)
import requests
post_group_id = '507f1f77bcf86cd799439011'
response = requests.get(
f'https://api.postpost.dev/api/v1/post-logs/{post_group_id}',
headers={'x-api-key': 'YOUR_API_KEY'}
)
logs = response.json()['logs']
# Find failed publish attempts
failures = [l for l in logs if l['event'] == 'publish_failed']
for failure in failures:
print(f"❌ {failure['platform']}: {failure['error']}")
if failure.get('metadata', {}).get('retryable'):
print(" (This error may succeed on retry)")cURL
curl https://api.postpost.dev/api/v1/post-logs/507f1f77bcf86cd799439011 \
-H "x-api-key: YOUR_API_KEY"Debug Failed Post
async function debugFailedPost(postGroupId) {
const [postResponse, logsResponse] = await Promise.all([
fetch(`https://api.postpost.dev/api/v1/get-post/${postGroupId}`, {
headers: { 'x-api-key': process.env.PUBLORA_API_KEY }
}),
fetch(`https://api.postpost.dev/api/v1/post-logs/${postGroupId}`, {
headers: { 'x-api-key': process.env.PUBLORA_API_KEY }
})
]);
const postData = await postResponse.json();
const logsData = await logsResponse.json();
console.log('=== Post Status ===');
for (const post of postData.posts) {
console.log(`${post.platform}: ${post.status}`);
if (post.error) {
console.log(` Error: ${post.error.code} - ${post.error.message}`);
console.log(` Retryable: ${post.error.retryable}`);
}
}
console.log('\n=== Timeline ===');
for (const log of logsData.logs) {
const time = new Date(log.createdAt).toISOString();
console.log(`[${time}] ${log.platform}: ${log.event}`);
if (log.error) {
console.log(` └─ ${log.error}`);
}
}
}Errors
| Status | Error | Cause |
|---|---|---|
| 400 | "Invalid x-postpost-user-id" | The x-postpost-user-id header value is not a valid ID |
| 401 | "API key is required" | x-api-key header is missing entirely |
| 401 | "Invalid API key" | x-api-key is present but invalid |
| 401 | "Invalid API key owner" | API key exists but the associated user account was not found |
| 403 | "API access is not enabled for this account" | The user's account does not have API access enabled |
| 403 | "MCP access is not enabled for this account" | The x-postpost-client: mcp header was sent but entitlements.features.mcpAccess is not enabled |
| 403 | "Workspace access is not enabled for this key" | API key does not have workspace access enabled |
| 403 | "User is not managed by key" | Managed user does not belong to the API key owner's workspace |
| 404 | "Post group not found" | Invalid ID or post belongs to another user |
| 500 | "Failed to get post logs" | Server error |
Note: If an invalid ObjectId format is passed as
postGroupId(e.g., a non-hex string or wrong length), the endpoint returns500 "Failed to get post logs"instead of404 "Post group not found". This is because Mongoose throws aCastErrorfor invalid ObjectIds, which is caught by the generic error handler before the post group lookup can return a 404.