{
  "openapi": "3.0.3",
  "info": {
    "title": "wavpost",
    "version": "1.0.0",
    "description": "Unified social media API. Publish to LinkedIn, X (Twitter), YouTube, and TikTok from a single call. Automate likes, follows, DMs, and more.",
    "contact": {
      "url": "https://wavpost.com"
    }
  },
  "servers": [
    {
      "url": "https://api.wavpost.com",
      "description": "Production API"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key only: Authorization: Bearer sk_live_... (Firebase ID tokens are not accepted)"
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "paths": {
    "/api/v1/posts": {
      "get": {
        "summary": "List posts",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Posts"
        ],
        "responses": {
          "200": {
            "description": "{ posts: [...] } — array of post records with per-platform results"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Publish a post",
        "description": "Publish to one or more platforms simultaneously. Credits charged only for platforms that succeed. Twitter/X requires a paid plan.\n\n**Credits:** Variable credits (depends on platforms selected)",
        "tags": [
          "Posts"
        ],
        "responses": {
          "201": {
            "description": "Post object with id, status, platformResults map per platform (ok, platformPostId or error)"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text",
                  "platforms"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "Post content. Twitter: max 280 chars."
                  },
                  "platforms": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "linkedin",
                        "twitter",
                        "youtube",
                        "tiktok",
                        "facebook",
                        "instagram"
                      ]
                    },
                    "description": "Platforms to publish to"
                  },
                  "mediaUrls": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Public media URLs. LinkedIn: images (up to 9). YouTube/TikTok: video URL. Twitter: ignored (text-only)."
                  },
                  "scheduledFor": {
                    "type": "string",
                    "description": "ISO 8601 datetime — stored on post record; platforms are published immediately"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug (uses default profile if omitted)"
                  },
                  "meta": {
                    "type": "string",
                    "description": "Platform-specific metadata. Example: { \"youtube\": { \"title\": \"My Video\", \"tags\": [\"ai\", \"tech\"], \"categoryId\": \"28\", \"privacyStatus\": \"public\" } }"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/like": {
      "post": {
        "summary": "Like a tweet",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, liked: true }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_id"
                ],
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "description": "Tweet ID to like"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Unlike a tweet",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, unliked: true }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_id"
                ],
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "description": "Tweet ID to unlike"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/follow": {
      "post": {
        "summary": "Follow a Twitter user",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, following: true, pendingFollow: false }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target_user_id"
                ],
                "properties": {
                  "target_user_id": {
                    "type": "string",
                    "description": "Numeric Twitter user ID to follow"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Unfollow a Twitter user",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, following: false }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "target_user_id"
                ],
                "properties": {
                  "target_user_id": {
                    "type": "string",
                    "description": "Numeric Twitter user ID to unfollow"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/bookmark": {
      "post": {
        "summary": "Bookmark a tweet",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, bookmarked: true }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_id"
                ],
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "description": "Tweet ID to bookmark"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Remove a bookmark",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, bookmarkDeleted: true }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_id"
                ],
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "description": "Tweet ID to remove from bookmarks"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/dm": {
      "post": {
        "summary": "Send a direct message",
        "description": "Send a DM to a user. The recipient must allow DMs from your account.\n\n**Credits:** 2 credits — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, dmConversationId: '...', dmEventId: '...' }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "recipient_id",
                  "text"
                ],
                "properties": {
                  "recipient_id": {
                    "type": "string",
                    "description": "Numeric Twitter user ID of the recipient"
                  },
                  "text": {
                    "type": "string",
                    "description": "Message text"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/tweet": {
      "delete": {
        "summary": "Delete a tweet",
        "description": "**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, deleted: true }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_id"
                ],
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "description": "Tweet ID to delete"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/reply/hide": {
      "put": {
        "summary": "Hide or unhide a reply",
        "description": "Hide or unhide a reply on one of your own tweets. You cannot hide replies on other users' tweets.\n\n**Credits:** 1 credit — requires paid plan (Starter or higher)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, hidden: true }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tweet_id"
                ],
                "properties": {
                  "tweet_id": {
                    "type": "string",
                    "description": "Tweet ID of the reply to hide/unhide"
                  },
                  "hidden": {
                    "type": "boolean",
                    "description": "true to hide, false to unhide (defaults to true)"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/twitter/timeline": {
      "get": {
        "summary": "Get home timeline",
        "description": "Fetch recent tweets from the authenticated user's home timeline. Free — does not consume credits.\n\n**Credits:** Free (0 credits)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, tweets: [...], count: N }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "max_results",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Number of tweets to return",
              "default": 10,
              "minimum": 5,
              "maximum": 100
            },
            "description": "Number of tweets to return"
          },
          {
            "name": "profile",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Profile slug"
            },
            "description": "Profile slug"
          }
        ]
      }
    },
    "/api/v1/twitter/user": {
      "get": {
        "summary": "Look up a Twitter user by username",
        "description": "Get a user's public profile by @username. Free — does not consume credits.\n\n**Credits:** Free (0 credits)",
        "tags": [
          "Twitter Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, user: { id, name, username } }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Twitter username without the @ symbol"
            },
            "description": "Twitter username without the @ symbol"
          },
          {
            "name": "profile",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Profile slug"
            },
            "description": "Profile slug"
          }
        ]
      }
    },
    "/api/v1/linkedin/post": {
      "delete": {
        "summary": "Delete a LinkedIn post",
        "description": "**Credits:** 1 credit",
        "tags": [
          "LinkedIn Actions"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true, deleted: true, postUrn: '...' }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "post_urn"
                ],
                "properties": {
                  "post_urn": {
                    "type": "string",
                    "description": "LinkedIn post URN, e.g. urn:li:share:1234 or urn:li:ugcPost:1234"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/linkedin/reshare": {
      "post": {
        "summary": "Reshare a LinkedIn post",
        "description": "**Credits:** 1 credit",
        "tags": [
          "LinkedIn Actions"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, reshareId: 'urn:li:share:...' }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "post_urn"
                ],
                "properties": {
                  "post_urn": {
                    "type": "string",
                    "description": "LinkedIn post URN to reshare"
                  },
                  "commentary": {
                    "type": "string",
                    "description": "Optional text to add to the reshare"
                  },
                  "profile": {
                    "type": "string",
                    "description": "Profile slug"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/usage": {
      "get": {
        "summary": "Get plan, credit balance, and recent transactions",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Billing"
        ],
        "responses": {
          "200": {
            "description": "{ plan: { id, label, price }, credits: { balance, monthlyAllowance, used, resetAt }, recentTransactions: [...] }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/profiles": {
      "get": {
        "summary": "List profiles",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Profiles"
        ],
        "responses": {
          "200": {
            "description": "{ profiles: [...] }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a profile",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Profiles"
        ],
        "responses": {
          "201": {
            "description": "{ profile: { id, name, slug, isDefault, createdAt } }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Profile display name"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/profiles/{profileId}": {
      "patch": {
        "summary": "Update a profile",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Profiles"
        ],
        "responses": {
          "200": {
            "description": "Updated profile object"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "profileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "New display name"
                  },
                  "isDefault": {
                    "type": "boolean",
                    "description": "Set as default profile"
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete a profile",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Profiles"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "profileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/logs": {
      "get": {
        "summary": "Get activity logs",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Logs"
        ],
        "responses": {
          "200": {
            "description": "{ logs: [...], total, limit, offset }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Number of logs to return (max 200)",
              "default": 50,
              "maximum": 200
            },
            "description": "Number of logs to return (max 200)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "description": "Pagination offset",
              "default": 0
            },
            "description": "Pagination offset"
          }
        ]
      }
    },
    "/api/keys": {
      "get": {
        "summary": "List API keys",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "API Keys"
        ],
        "responses": {
          "200": {
            "description": "{ keys: [{ id, name, keyPreview, createdAt, lastUsedAt }] }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create an API key",
        "description": "Creates a new API key. The rawKey value is returned only once — store it securely immediately.\n\n**Credits:** Free (0 credits)",
        "tags": [
          "API Keys"
        ],
        "responses": {
          "201": {
            "description": "{ key: { id, name, keyPreview, createdAt }, rawKey: 'sk_live_...' }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "name"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Label for the key"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/keys/{keyId}": {
      "delete": {
        "summary": "Revoke an API key",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "API Keys"
        ],
        "responses": {
          "200": {
            "description": "{ ok: true }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/connect/status": {
      "get": {
        "summary": "Get connection status for all platforms",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Connections"
        ],
        "responses": {
          "200": {
            "description": "{ linkedin: { connected: true, displayName: \"Jane\" }, twitter: { connected: false } }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "profileId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Profile ID (uses default profile if omitted)"
            },
            "description": "Profile ID (uses default profile if omitted)"
          }
        ]
      }
    },
    "/api/auth/{platform}": {
      "get": {
        "summary": "Start OAuth flow (browser redirect)",
        "description": "Browser-only. Redirects to the OAuth provider. platform ∈ linkedin | twitter | youtube | tiktok\n\n**Credits:** Free (0 credits)",
        "tags": [
          "Connections"
        ],
        "responses": {
          "200": {
            "description": "302 redirect to OAuth provider"
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [],
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "profileId",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Optional profile UUID"
            },
            "description": "Optional profile UUID"
          }
        ]
      }
    },
    "/api/connect/{platform}/options": {
      "get": {
        "summary": "List OAuth account options after callback",
        "description": "Requires temp session cookie set by the OAuth callback. Returns selectable accounts (personal + orgs).\n\n**Credits:** Free (0 credits)",
        "tags": [
          "Connections"
        ],
        "responses": {
          "200": {
            "description": "{ options: [{ accountId, name, description, type, picture?, accountUrn? }] }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Upstream provider error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [],
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/api/connect/{platform}/confirm": {
      "post": {
        "summary": "Confirm OAuth account selection",
        "description": "Saves the chosen account as a platform connection. Requires dashboard session cookie (not API key).\n\n**Credits:** Free (0 credits)",
        "tags": [
          "Connections"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, redirect: '/dashboard/connections' }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "option"
                ],
                "properties": {
                  "option": {
                    "type": "string",
                    "description": "One option object from GET /options"
                  },
                  "profileId": {
                    "type": "string",
                    "description": "Profile UUID (default profile if omitted)"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/connect/{platform}/disconnect": {
      "post": {
        "summary": "Disconnect a platform",
        "description": "**Credits:** Free (0 credits)",
        "tags": [
          "Connections"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true }"
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "platform",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "profileId": {
                    "type": "string",
                    "description": "Profile UUID (default profile if omitted)"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/webhooks/incoming": {
      "post": {
        "summary": "Receive content and auto-publish to social media",
        "description": "Accepts article/blog content payloads (e.g. from ClyroAI or similar SEO tools) and publishes them to the specified social platforms. Authenticate with Authorization: Bearer or X-API-Key header. Use ?test=true or set body.test=true for a dry-run without posting.\n\n**Credits:** Variable credits (depends on platforms selected)",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "201": {
            "description": "{ ok: true, postId: '...', platforms: { linkedin: { ok, platformPostId }, ... } }"
          },
          "400": {
            "description": "Bad request — invalid or missing fields",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized — missing or invalid Bearer token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden — paid plan required or action not permitted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "platforms",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "linkedin",
                "twitter",
                "youtube",
                "tiktok",
                "facebook",
                "instagram"
              ],
              "description": "Comma-separated platform list (default: linkedin,twitter)"
            },
            "description": "Comma-separated platform list (default: linkedin,twitter)"
          },
          {
            "name": "profile",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Profile slug (uses default if omitted)"
            },
            "description": "Profile slug (uses default if omitted)"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "body"
                ],
                "properties": {
                  "title": {
                    "type": "string",
                    "description": "Article title — prepended to post text"
                  },
                  "body": {
                    "type": "string",
                    "description": "Article body / content"
                  },
                  "keyword": {
                    "type": "string",
                    "description": "Primary keyword — appended as a hashtag"
                  },
                  "status": {
                    "type": "string",
                    "description": "Set to 'test' for a dry-run"
                  },
                  "timestamp": {
                    "type": "string",
                    "description": "ISO 8601 publish datetime (stored as scheduledFor)"
                  },
                  "test": {
                    "type": "boolean",
                    "description": "true for a dry-run (no post created)"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Posts",
      "description": "Publish and list posts across all connected platforms"
    },
    {
      "name": "Twitter Actions",
      "description": "Twitter/X-specific actions: like, follow, bookmark, DM, delete tweet, hide reply, timeline, user lookup. Write actions require a paid plan."
    },
    {
      "name": "LinkedIn Actions",
      "description": "LinkedIn-specific actions: delete post, reshare. Available on any plan. Reactions and comments require LinkedIn Partnership (not available)."
    },
    {
      "name": "Billing",
      "description": "Plan info, credit balance, and transaction history"
    },
    {
      "name": "Profiles",
      "description": "Manage workspace profiles (group connections by brand/client)"
    },
    {
      "name": "Logs",
      "description": "Activity and audit logs"
    },
    {
      "name": "API Keys",
      "description": "Create and revoke API keys for programmatic access"
    },
    {
      "name": "Connections",
      "description": "Connect and manage social platform OAuth accounts"
    },
    {
      "name": "Webhooks",
      "description": ""
    }
  ]
}
