{"openapi":"3.1.0","info":{"title":"Ubiqlu API","version":"1.0.0","description":"Workspace-scoped REST API for the full publishing flow: discover a workspace, create Campaigns, add independent content pieces, list connected social accounts, upload media, schedule or publish Posts, poll publish status, and retry failed targets. Authenticate with a workspace API key sent as a bearer token; every key is scoped to one workspace and cannot cross workspace boundaries."},"servers":[{"url":"https://ubiqlu.com/api/v1"}],"paths":{"/workspaces":{"get":{"tags":["Workspaces"],"summary":"Discover the key workspace","description":"Returns the single workspace the API key unlocks, so an agent can learn its workspace id, slug, and timezone from a key alone.","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Workspace returned.","content":{"application/json":{"schema":{"type":"object","properties":{"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/Workspace"}}},"required":["workspaces"],"additionalProperties":false},"example":{"workspaces":[{"id":"workspace_id","name":"Acme","slug":"acme","timezone":"America/New_York","brandSummary":"Indie hardware studio.","createdAt":"2026-06-01T09:00:00.000Z"}]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Workspace not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/social-accounts":{"get":{"tags":["Accounts"],"summary":"List social accounts","description":"Returns the connected social accounts in a workspace. Use the returned ids as socialAccountIds when creating a post.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and accounts."}],"responses":{"200":{"description":"Social accounts returned.","content":{"application/json":{"schema":{"type":"object","properties":{"accounts":{"type":"array","items":{"$ref":"#/components/schemas/SocialAccount"}}},"required":["accounts"],"additionalProperties":false},"example":{"accounts":[{"id":"social_account_id","platform":"instagram","providerVariant":"instagram_business_login","displayName":"Acme","handle":"acme","avatarUrl":"https://cdn.example.com/avatar.png","status":"connected","health":{"state":"connected","needsReconnect":false,"label":"Connected","detail":null},"tokenExpiresAt":"2026-08-01T09:00:00.000Z","connectedAt":"2026-06-01T09:00:00.000Z","lastUsedAt":"2026-06-05T14:30:00.000Z"}]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, or inactive entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/media":{"get":{"tags":["Media"],"summary":"List media assets","description":"Returns the latest media assets registered inside one workspace.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and media assets."}],"responses":{"200":{"description":"Media assets returned.","content":{"application/json":{"schema":{"type":"object","properties":{"assets":{"type":"array","items":{"$ref":"#/components/schemas/MediaAsset"}}},"required":["assets"],"additionalProperties":false},"example":{"assets":[{"id":"media_asset_id","fileName":"launch-image.png","publicUrl":"https://cdn.example.com/workspaces/{workspaceId}/2026-06/asset.png","mimeType":"image/png","bytes":245760,"width":1200,"height":800,"durationSeconds":null,"postTypeHint":"feed_image","createdAt":"2026-06-02T10:15:00.000Z"}]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, or inactive entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Media"],"summary":"Finalize uploaded media","description":"Verifies an uploaded object, stores its metadata, and returns the registered media asset.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and uploaded object."}],"responses":{"201":{"description":"Media asset registered or returned on retry.","content":{"application/json":{"schema":{"type":"object","properties":{"asset":{"$ref":"#/components/schemas/MediaAsset"}},"required":["asset"],"additionalProperties":false},"example":{"asset":{"id":"media_asset_id","fileName":"launch-image.png","publicUrl":"https://cdn.example.com/workspaces/{workspaceId}/2026-06/asset.png","mimeType":"image/png","bytes":245760,"width":1200,"height":800,"durationSeconds":null,"postTypeHint":"feed_image","createdAt":"2026-06-02T10:15:00.000Z"}}}}},"400":{"description":"Invalid body or unsupported media type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, inactive entitlement, or foreign storage key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Uploaded object could not be verified against metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileName":{"type":"string","description":"Display file name for the stored media asset."},"storageKey":{"type":"string","minLength":1,"description":"Storage key returned by the upload-url endpoint."},"mimeType":{"type":"string","enum":["image/jpeg","image/png","video/mp4"],"description":"Expected object content type."},"bytes":{"type":"integer","exclusiveMinimum":0,"maximum":8388608,"description":"Expected object size in bytes. Maximum: 8.0 MB."},"width":{"description":"Image or video width when known.","anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"height":{"description":"Image or video height when known.","anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]},"durationSeconds":{"description":"Video duration when known.","anyOf":[{"type":"integer","minimum":0,"maximum":9007199254740991},{"type":"null"}]}},"required":["fileName","storageKey","mimeType","bytes"]},"example":{"fileName":"launch-image.png","storageKey":"workspaces/{workspaceId}/2026-06/asset.png","mimeType":"image/png","bytes":245760,"width":1200,"height":800}}}}}},"/workspaces/{workspaceId}/media/upload-url":{"post":{"tags":["Media"],"summary":"Create an upload URL","description":"Returns a short-lived Cloudflare R2 upload URL plus the storage key to finalize later.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and future media asset."}],"responses":{"200":{"description":"Upload URL created.","content":{"application/json":{"schema":{"type":"object","properties":{"uploadUrl":{"type":"string","format":"uri","description":"Short-lived Cloudflare R2 upload URL."},"expiresInSeconds":{"type":"number","description":"Seconds until the upload URL expires."},"storageKey":{"type":"string","description":"Storage key to pass back to the finalize endpoint."},"publicUrl":{"type":"string","format":"uri","description":"Durable public URL the finalized asset will be served from."}},"required":["uploadUrl","expiresInSeconds","storageKey","publicUrl"],"additionalProperties":false},"example":{"uploadUrl":"https://...","expiresInSeconds":900,"storageKey":"workspaces/{workspaceId}/2026-06/asset.png","publicUrl":"https://cdn.example.com/workspaces/{workspaceId}/2026-06/asset.png"}}}},"400":{"description":"Invalid file name, MIME type, or file size.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, or inactive entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fileName":{"type":"string","minLength":1,"description":"Original file name for display and metadata."},"mimeType":{"type":"string","enum":["image/jpeg","image/png","video/mp4"],"description":"Supported upload content type."},"bytes":{"type":"integer","exclusiveMinimum":0,"maximum":8388608,"description":"File size in bytes. Maximum: 8.0 MB."}},"required":["fileName","mimeType","bytes"]},"example":{"fileName":"launch-image.png","mimeType":"image/png","bytes":245760}}}}}},"/workspaces/{workspaceId}/campaigns":{"get":{"tags":["Campaigns"],"summary":"List campaigns","description":"Returns active campaigns by recent activity. Add archived=true for archived campaigns and search to match campaign or content text.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and campaigns."},{"name":"archived","in":"query","required":false,"schema":{"type":"string"},"description":"Set to true to return archived Campaigns."},{"name":"search","in":"query","required":false,"schema":{"type":"string"},"description":"Match Campaign names, briefs, or content text."}],"responses":{"200":{"description":"Campaigns returned.","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/Campaign"}}},"required":["campaigns"],"additionalProperties":false},"example":{"campaigns":[]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace or missing scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["Campaigns"],"summary":"Create a campaign","description":"Creates the product-facing parent for one idea. Platforms, accounts, and schedules belong to child content pieces, not this request.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and campaign."}],"responses":{"201":{"description":"Campaign created.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Campaign"}},"required":["campaign"],"additionalProperties":false},"example":{"campaign":{"id":"campaign_id","workspaceId":"workspace_id","name":"August product launch","brief":"Announce campaign-based publishing.","archivedAt":null,"createdAt":"2026-08-19T09:00:00.000Z","updatedAt":"2026-08-19T09:00:00.000Z","summary":{"counts":{"total":0,"draft":0,"scheduled":0,"publishing":0,"published":0,"failed":0},"humanSummary":"0 pieces","nextScheduledAt":null,"needsAttention":false},"posts":[]}}}}},"400":{"description":"Invalid name or brief.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace or missing scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"brief":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["name"]},"example":{"name":"August product launch","brief":"Announce campaign-based publishing."}}}}}},"/workspaces/{workspaceId}/campaigns/{campaignId}":{"get":{"tags":["Campaigns"],"summary":"Get a campaign","description":"Returns one campaign, its derived summary, and independent child content pieces.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the campaign."},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign to return."}],"responses":{"200":{"description":"Campaign returned.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Campaign"}},"required":["campaign"],"additionalProperties":false},"example":{"campaign":{"id":"campaign_id","workspaceId":"workspace_id","name":"August product launch","brief":null,"archivedAt":null,"createdAt":"2026-08-19T09:00:00.000Z","updatedAt":"2026-08-19T09:00:00.000Z","summary":{"counts":{"total":0,"draft":0,"scheduled":0,"publishing":0,"published":0,"failed":0},"humanSummary":"0 pieces","nextScheduledAt":null,"needsAttention":false},"posts":[]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace or missing scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Campaign not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Campaigns"],"summary":"Update a campaign","description":"Updates the name or brief, or archives/unarchives the campaign without changing child publish state.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the campaign."},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign to update."}],"responses":{"200":{"description":"Campaign updated.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Campaign"}},"required":["campaign"],"additionalProperties":false},"example":{"campaign":{"id":"campaign_id","workspaceId":"workspace_id","name":"September product launch","brief":null,"archivedAt":null,"createdAt":"2026-08-19T09:00:00.000Z","updatedAt":"2026-08-19T10:00:00.000Z","summary":{"counts":{"total":0,"draft":0,"scheduled":0,"publishing":0,"published":0,"failed":0},"humanSummary":"0 pieces","nextScheduledAt":null,"needsAttention":false},"posts":[]}}}}},"400":{"description":"Invalid update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace or missing scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Campaign not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"brief":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]},"archived":{"type":"boolean"}}},"example":{"name":"September product launch","archived":false}}}}},"delete":{"tags":["Campaigns"],"summary":"Delete or archive a campaign","description":"Soft-deletes an empty or draft-only campaign. A campaign with publishing history is archived instead so child state is preserved.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the campaign."},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign to delete or archive."}],"responses":{"200":{"description":"Campaign deleted or archived safely.","content":{"application/json":{"schema":{"type":"object","properties":{"outcome":{"type":"string","enum":["deleted","archived"]}},"required":["outcome"],"additionalProperties":false},"example":{"outcome":"archived"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace or missing scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Campaign not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/campaigns/{campaignId}/posts":{"post":{"tags":["Campaigns"],"summary":"Create campaign content","description":"Creates one independently editable Post inside a Campaign. Drafts may omit socialAccountIds; scheduling and publishing require compatible accounts.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the campaign."},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string"},"description":"Campaign that owns the new Post."}],"responses":{"201":{"description":"Campaign content created.","content":{"application/json":{"schema":{"type":"object","properties":{"post":{"$ref":"#/components/schemas/Post"}},"required":["post"],"additionalProperties":false},"example":{"post":{"id":"post_id","campaignId":"campaign_id","campaign":{"id":"campaign_id","name":"August product launch"},"platform":"linkedin","format":"text","caption":"Launch day is here.","title":null,"aggregateStatus":"draft","resolvedAt":null,"createdAt":"2026-08-19T09:00:00.000Z","targets":[],"media":[]}}}}},"400":{"description":"Invalid content or campaign state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace or missing scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"platform":{"anyOf":[{"type":"string","enum":["linkedin","instagram","facebook"]},{"type":"null"}]},"format":{"anyOf":[{"type":"string","enum":["text","image","video","reel"]},{"type":"null"}]},"caption":{"type":"string","description":"Post caption. Trimmed before use. May be empty for a draft or when media is attached."},"mediaAssetId":{"anyOf":[{"type":"string","description":"Media asset id from the media endpoints. Omit or null for text-only posts."},{"type":"null"}]},"mediaAssetIds":{"default":[],"description":"Ordered media asset ids from the media endpoints. The first item is the cover.","maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"socialAccountIds":{"default":[],"description":"Connected social account ids. Optional for drafts and required for scheduling or publishing.","type":"array","items":{"type":"string","minLength":1}},"timing":{"default":"now","type":"string","enum":["draft","scheduled","now"],"description":"Publish timing. Defaults to 'now' when omitted."},"scheduledAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 date-time in UTC. Required when timing is 'scheduled'."},{"type":"null"}]}}},"example":{"platform":"linkedin","format":"text","caption":"Launch day is here.","timing":"draft"}}}}}},"/workspaces/{workspaceId}/posts":{"post":{"tags":["Posts"],"summary":"Create a post","description":"Creates a post and its per-account publish targets. campaignId is optional for compatibility; when omitted, Ubiqlu creates a singleton campaign. Drafts may omit accounts. Set timing to 'scheduled' with scheduledAt to publish later, or 'now' to publish immediately.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key, media, and accounts."}],"responses":{"201":{"description":"Post created and targets dispatched.","content":{"application/json":{"schema":{"type":"object","properties":{"post":{"$ref":"#/components/schemas/Post"}},"required":["post"],"additionalProperties":false},"example":{"post":{"id":"post_id","campaignId":"campaign_id","campaign":{"id":"campaign_id","name":"Launch day is here."},"platform":null,"format":null,"caption":"Launch day is here.","title":null,"aggregateStatus":"publishing","resolvedAt":"2026-06-06T12:00:00.000Z","createdAt":"2026-06-06T12:00:00.000Z","targets":[{"id":"post_target_id","status":"publishing","platformPostUrl":null,"errorMessage":null,"errorContext":null,"scheduledAt":null,"publishedAt":null,"socialAccount":{"displayName":"Acme","handle":"acme","avatarUrl":"https://cdn.example.com/avatar.png","platform":"instagram"}}],"media":[{"id":"post_media_id","position":0,"publicUrl":"https://cdn.example.com/workspaces/{workspaceId}/2026-06/asset.png","mimeType":"image/png","fileName":"launch-image.png"}]}}}}},"400":{"description":"Invalid caption, media, accounts, timing, or scheduledAt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, or inactive entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"campaignId":{"anyOf":[{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},{"type":"null"}]},"platform":{"anyOf":[{"type":"string","enum":["linkedin","instagram","facebook"]},{"type":"null"}]},"format":{"anyOf":[{"type":"string","enum":["text","image","video","reel"]},{"type":"null"}]},"caption":{"type":"string","description":"Post caption. Trimmed before use. May be empty for a draft or when media is attached."},"mediaAssetId":{"anyOf":[{"type":"string","description":"Media asset id from the media endpoints. Omit or null for text-only posts."},{"type":"null"}]},"mediaAssetIds":{"default":[],"description":"Ordered media asset ids from the media endpoints. The first item is the cover.","maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"socialAccountIds":{"default":[],"description":"Connected social account ids. Optional for drafts and required for scheduling or publishing.","type":"array","items":{"type":"string","minLength":1}},"timing":{"default":"now","type":"string","enum":["draft","scheduled","now"],"description":"Publish timing. Defaults to 'now' when omitted."},"scheduledAt":{"anyOf":[{"type":"string","format":"date-time","description":"ISO 8601 date-time in UTC. Required when timing is 'scheduled'."},{"type":"null"}]}}},"examples":{"Draft (saved, not published)":{"value":{"caption":"Launch day is here.","mediaAssetId":"media_asset_id","timing":"draft"}},"Scheduled carousel or multi-image post":{"value":{"caption":"Launch day is here.","mediaAssetIds":["cover_media_id","second_media_id"],"socialAccountIds":["social_account_id"],"timing":"scheduled","scheduledAt":"2026-06-10T15:00:00.000Z"}},"Publish now":{"value":{"caption":"Launch day is here.","mediaAssetId":"media_asset_id","socialAccountIds":["social_account_id"],"timing":"now"}}}}}}}},"/workspaces/{workspaceId}/posts/{postId}":{"get":{"tags":["Posts"],"summary":"Get post status","description":"Returns one post with its per-account publish targets and media, so callers can poll publish status and read published URLs or failure reasons.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and post."},{"name":"postId","in":"path","required":true,"schema":{"type":"string"},"description":"Post to read status for."}],"responses":{"200":{"description":"Post returned.","content":{"application/json":{"schema":{"type":"object","properties":{"post":{"$ref":"#/components/schemas/Post"}},"required":["post"],"additionalProperties":false},"example":{"post":{"id":"post_id","campaignId":"campaign_id","campaign":{"id":"campaign_id","name":"Launch day is here."},"platform":null,"format":null,"caption":"Launch day is here.","title":null,"aggregateStatus":"published","resolvedAt":"2026-06-06T12:01:30.000Z","createdAt":"2026-06-06T12:00:00.000Z","targets":[{"id":"post_target_id","status":"published","platformPostUrl":"https://www.instagram.com/p/abc123/","errorMessage":null,"errorContext":null,"scheduledAt":null,"publishedAt":"2026-06-06T12:01:30.000Z","socialAccount":{"displayName":"Acme","handle":"acme","avatarUrl":"https://cdn.example.com/avatar.png","platform":"instagram"}}],"media":[]}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, or inactive entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Post not found in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/post-targets/{targetId}/retry":{"post":{"tags":["Posts"],"summary":"Retry a publish target","description":"Re-dispatches a failed publish target through the durable publish pipeline. Only failed targets can be retried; in-flight targets are rejected.","security":[{"bearerAuth":[]}],"parameters":[{"name":"workspaceId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace that owns the API key and target."},{"name":"targetId","in":"path","required":true,"schema":{"type":"string"},"description":"Failed publish target id (from the post targets array)."}],"responses":{"200":{"description":"Retry dispatched.","content":{"application/json":{"schema":{"type":"object","properties":{"postId":{"type":"string","description":"Post that owns the retried target."},"postTargetId":{"type":"string","description":"Publish target that was re-dispatched."},"publishJobId":{"type":"string","description":"Durable publish job created for the retry."}},"required":["postId","postTargetId","publishJobId"],"additionalProperties":false},"example":{"postId":"post_id","postTargetId":"post_target_id","publishJobId":"publish_job_id"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Wrong workspace, missing scope, or inactive entitlement.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Publish target not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Target is not failed or a retry is already in progress.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Ubiqlu API key"}},"schemas":{"Workspace":{"type":"object","properties":{"id":{"type":"string","description":"Workspace identifier the API key unlocks."},"name":{"type":"string","description":"Workspace display name."},"slug":{"type":"string","description":"URL-safe workspace slug."},"timezone":{"type":"string","description":"IANA timezone used for scheduling."},"brandSummary":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional brand summary used for context."},"createdAt":{"type":"string","format":"date-time","description":"ISO timestamp the workspace was created."}},"required":["id","name","slug","timezone","brandSummary","createdAt"],"additionalProperties":false},"SocialAccount":{"type":"object","properties":{"id":{"type":"string","description":"Social account identifier."},"platform":{"type":"string","enum":["instagram","linkedin","facebook"],"description":"Connected platform."},"providerVariant":{"type":"string","enum":["instagram_business_login","linkedin_personal","linkedin_company","facebook_page"],"description":"Connection variant for the platform."},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Account display name."},"handle":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Account handle or username."},"avatarUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"description":"Avatar image URL."},"status":{"type":"string","enum":["connected","token_expiring","disconnected","error"],"description":"Stored connection status."},"health":{"type":"object","properties":{"state":{"type":"string","enum":["connected","token_expiring","disconnected","error"]},"needsReconnect":{"type":"boolean"},"label":{"type":"string"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["state","needsReconnect","label","detail"],"additionalProperties":false,"description":"Live health used to decide whether a reconnect is needed."},"tokenExpiresAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp when the access token expires."},"connectedAt":{"type":"string","format":"date-time","description":"ISO timestamp when the account was connected."},"lastUsedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp of the last publish that used this account."}},"required":["id","platform","providerVariant","displayName","handle","avatarUrl","status","health","tokenExpiresAt","connectedAt","lastUsedAt"],"additionalProperties":false},"MediaAsset":{"type":"object","properties":{"id":{"type":"string","description":"Media asset identifier."},"fileName":{"type":"string","description":"Display name."},"publicUrl":{"type":"string","format":"uri","description":"Durable public URL for provider publishing."},"mimeType":{"type":"string","enum":["image/jpeg","image/png","video/mp4"],"description":"Stored media content type."},"bytes":{"type":"number","description":"File size in bytes."},"width":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Pixel width when known."},"height":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Pixel height when known."},"durationSeconds":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Video duration when known."},"postTypeHint":{"anyOf":[{"type":"string","enum":["feed_image","feed_video","reel"]},{"type":"null"}],"description":"Provider hint for how to publish the asset."},"createdAt":{"type":"string","format":"date-time","description":"ISO timestamp."}},"required":["id","fileName","publicUrl","mimeType","bytes","width","height","durationSeconds","postTypeHint","createdAt"],"additionalProperties":false},"Campaign":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"name":{"type":"string"},"brief":{"anyOf":[{"type":"string"},{"type":"null"}]},"archivedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"summary":{"type":"object","properties":{"counts":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"maximum":9007199254740991},"draft":{"type":"integer","minimum":0,"maximum":9007199254740991},"scheduled":{"type":"integer","minimum":0,"maximum":9007199254740991},"publishing":{"type":"integer","minimum":0,"maximum":9007199254740991},"published":{"type":"integer","minimum":0,"maximum":9007199254740991},"failed":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["total","draft","scheduled","publishing","published","failed"],"additionalProperties":false},"humanSummary":{"type":"string"},"nextScheduledAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"needsAttention":{"type":"boolean"}},"required":["counts","humanSummary","nextScheduledAt","needsAttention"],"additionalProperties":false},"posts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"campaignId":{"type":"string"},"platform":{"anyOf":[{"type":"string","enum":["instagram","linkedin","facebook"]},{"type":"null"}]},"format":{"anyOf":[{"type":"string","enum":["text","image","video","reel"]},{"type":"null"}]},"title":{"anyOf":[{"type":"string"},{"type":"null"}]},"caption":{"anyOf":[{"type":"string"},{"type":"null"}]},"aggregateStatus":{"type":"string","enum":["draft","scheduled","publishing","published","partially_published","failed"]},"scheduledAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}]},"updatedAt":{"type":"string","format":"date-time"},"needsAttention":{"type":"boolean"},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"position":{"type":"integer","minimum":0,"maximum":9007199254740991},"publicUrl":{"type":"string","format":"uri"},"mimeType":{"type":"string"},"fileName":{"type":"string"}},"required":["id","position","publicUrl","mimeType","fileName"],"additionalProperties":false}}},"required":["id","campaignId","platform","format","title","caption","aggregateStatus","scheduledAt","updatedAt","needsAttention","media"],"additionalProperties":false}}},"required":["id","workspaceId","name","brief","archivedAt","createdAt","updatedAt","summary","posts"],"additionalProperties":false},"Post":{"type":"object","properties":{"id":{"type":"string","description":"Post identifier."},"campaignId":{"type":"string","description":"Campaign that owns this post."},"campaign":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"],"additionalProperties":false},"platform":{"anyOf":[{"type":"string","enum":["instagram","linkedin","facebook"]},{"type":"null"}]},"format":{"anyOf":[{"type":"string","enum":["text","image","video","reel"]},{"type":"null"}]},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Post caption."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional post title."},"aggregateStatus":{"type":"string","enum":["draft","scheduled","publishing","published","partially_published","failed"],"description":"Roll-up status across every publish target."},"resolvedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp the post published or is scheduled for."},"createdAt":{"type":"string","format":"date-time","description":"ISO timestamp the post was created."},"targets":{"type":"array","items":{"$ref":"#/components/schemas/PostTarget"},"description":"Per-account publish targets."},"media":{"type":"array","items":{"$ref":"#/components/schemas/PostMedia"},"description":"Media attached to the post, ordered by position."}},"required":["id","campaignId","campaign","platform","format","caption","title","aggregateStatus","resolvedAt","createdAt","targets","media"],"additionalProperties":false},"PostTarget":{"type":"object","properties":{"id":{"type":"string","description":"Publish target identifier. Retry uses this id."},"status":{"type":"string","enum":["draft","scheduled","publishing","published","failed"],"description":"Per-account publish status."},"platformPostUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}],"description":"Live URL of the published post, once available."},"errorMessage":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Human-readable failure reason when the target failed."},"errorContext":{"anyOf":[{"type":"object","properties":{"body":{"type":"string"}},"required":["body"],"additionalProperties":false},{"type":"null"}],"description":"Raw provider error payload for debugging failed targets."},"scheduledAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp the target is scheduled to publish."},"publishedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"ISO timestamp the target was published."},"socialAccount":{"type":"object","properties":{"displayName":{"anyOf":[{"type":"string"},{"type":"null"}]},"handle":{"anyOf":[{"type":"string"},{"type":"null"}]},"avatarUrl":{"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"platform":{"type":"string","enum":["instagram","linkedin","facebook"]}},"required":["displayName","handle","avatarUrl","platform"],"additionalProperties":false,"description":"Account the target publishes to."}},"required":["id","status","platformPostUrl","errorMessage","errorContext","scheduledAt","publishedAt","socialAccount"],"additionalProperties":false},"PostMedia":{"type":"object","properties":{"id":{"type":"string","description":"Post media item identifier."},"position":{"type":"number","description":"Zero-based order within the post."},"publicUrl":{"type":"string","format":"uri","description":"Durable public URL of the attached media asset."},"mimeType":{"type":"string","description":"Content type of the attached media asset."},"fileName":{"type":"string","description":"Display name of the attached media asset."}},"required":["id","position","publicUrl","mimeType","fileName"],"additionalProperties":false},"Error":{"type":"object","properties":{"error":{"type":"string","description":"Human-readable error message."}},"required":["error"],"additionalProperties":false}}}}