{
  "openapi": "3.1.0",
  "info": {
    "title": "Lempile X API",
    "version": "1.0.0",
    "description": "Post, reply, like, repost, follow, pin, edit the profile and read on X from your own connected X accounts, each in its own browser with its own IP. Paths, fields and errors follow Unipile's where Unipile has the route."
  },
  "servers": [
    {
      "url": "https://api.lempile.com",
      "description": "Lempile production API"
    }
  ],
  "tags": [
    {
      "name": "Accounts",
      "description": "Your connected X accounts."
    },
    {
      "name": "Posts",
      "description": "Create, read, delete and pin posts; X's GIF search."
    },
    {
      "name": "Replies",
      "description": "Reply under posts and read replies."
    },
    {
      "name": "Likes, reposts and follows",
      "description": "Like, repost and follow; who liked a post; the account's followers."
    },
    {
      "name": "Search and reads",
      "description": "X search, a profile's posts, and the account's own posts, replies and reposts."
    },
    {
      "name": "Profile and analytics",
      "description": "The profile (pictures, name, bio, location, website, handle), read and edited, and the account's daily analytics."
    },
    {
      "name": "Page capture",
      "description": "A JPEG of a public X post, a status page or the account's own profile, from the account's own browser."
    },
    {
      "name": "Articles",
      "description": "X Articles, built and checked before they're published."
    },
    {
      "name": "Write receipts",
      "description": "What became of a write, by its Idempotency-Key."
    }
  ],
  "paths": {
    "/accounts": {
      "get": {
        "operationId": "X_listAccounts",
        "summary": "List accounts",
        "tags": ["Accounts"],
        "description": "The workspace's connected accounts, X and LinkedIn. An X account has `provider: \"x\"` and its handle in `public_identifier`. Read from Lempile's database: no browser opens.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "The accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{account_id}": {
      "get": {
        "operationId": "X_getAccount",
        "summary": "Retrieve an account",
        "tags": ["Accounts"],
        "description": "One account, in Unipile's shape. `sources[].status` is `OK` (ready), `CREDENTIALS` (sign-in or a check needed), `CONNECTING` or `ERROR`. No browser opens.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "path",
            "required": true,
            "description": "Lempile id, X user id or handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          }
        ],
        "responses": {
          "200": {
            "description": "The account.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "example": {
                  "object": "Account",
                  "id": "11111111-1111-4111-8111-111111111111",
                  "type": "X",
                  "name": "Jane Demo",
                  "created_at": "2026-10-08T09:00:00Z",
                  "sources": [
                    {
                      "id": "x_browser_session",
                      "status": "OK"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "X_deleteAccount",
        "summary": "Delete an account",
        "tags": ["Accounts"],
        "description": "Disconnects the account from the workspace. Its X account itself is untouched.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "path",
            "required": true,
            "description": "Lempile id, X user id or handle.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "const": "AccountDeleted"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts": {
      "post": {
        "operationId": "X_createPost",
        "summary": "Create a post",
        "tags": ["Posts"],
        "description": "Posts from the account's own X, in its own browser: words, up to 4 images or one video, or a GIF from X's GIF search. To reply, use `POST /posts/{post_id}/comments`.\n\nPaced per account (see Errors and limits): at least 45 seconds between writes and 70 writes in 24 hours. The request waits up to 140 seconds; if X doesn't confirm by then, the answer is `504 errors/timeout` and the receipt tells you what happened.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "1–200 characters of `A-Z a-z 0-9 . _ : -`. The same key with the same request replays the first answer; see Write receipts.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["account_id", "text"],
                "properties": {
                  "account_id": {
                    "type": "string",
                    "description": "The X account (also accepted as `?account_id=`)."
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 3000,
                    "description": "The post's words. More than 280 characters needs X Premium on the account: without it X keeps the post in its box and the answer is `422 errors/not_sent`."
                  },
                  "attachments": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "binary"
                    },
                    "description": "Multipart only: up to 4 images (JPEG, PNG, WebP or GIF, 8 MB each), or one MP4 of up to 50 MB on its own."
                  },
                  "gif": {
                    "type": "string",
                    "description": "A GIF from X's own GIF search, as JSON `{\"query\": \"...\", \"url\": \"...\"}` (a string in a form field): `query` 2–40 letters, digits, spaces, `'` or `-`; `url` a result from `GET /posts/gifs`. Not with attachments."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "Does everything but press Post: answers `200 PostDryRun`, nothing is posted."
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["account_id", "text"],
                "properties": {
                  "account_id": {
                    "type": "string",
                    "description": "The X account (also accepted as `?account_id=`)."
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 3000,
                    "description": "The post's words. More than 280 characters needs X Premium on the account: without it X keeps the post in its box and the answer is `422 errors/not_sent`."
                  },
                  "gif": {
                    "type": "string",
                    "description": "A GIF from X's own GIF search, as JSON `{\"query\": \"...\", \"url\": \"...\"}` (a string in a form field): `query` 2–40 letters, digits, spaces, `'` or `-`; `url` a result from `GET /posts/gifs`. Not with attachments."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "Does everything but press Post: answers `200 PostDryRun`, nothing is posted."
                  }
                }
              },
              "example": {
                "account_id": "janedemo",
                "text": "Shipping today."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Posted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostCreated"
                },
                "example": {
                  "object": "PostCreated",
                  "provider": "X",
                  "post_id": "1850000000000000001"
                }
              }
            }
          },
          "200": {
            "description": "Dry run: everything but the Post button.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostDryRun"
                }
              }
            }
          },
          "400": {
            "description": "`errors/missing_parameters`, `errors/invalid_parameters`, `errors/missing_idempotency_key` or `errors/invalid_idempotency_key`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`errors/in_progress`: the same key is still running or its outcome isn't known yet. `errors/account_busy`: an X Article is being built on this account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/not_sent` (the browser stopped before Post; `code` says why: `post_not_accepted` when X kept the post in its box, `gif_not_found`, `browser_busy`…), `errors/post_button_disabled`, `errors/idempotency_key_reused`, `errors/x_app_not_loaded`, `errors/proxy_auth_failed` or `errors/proxy_unreachable`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`errors/too_fast`, `errors/daily_limit` or `errors/browser_busy`, with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: Post was pressed but X didn't confirm in time. Read the receipt before sending again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/gifs": {
      "get": {
        "operationId": "X_searchGifs",
        "summary": "Search GIFs",
        "tags": ["Posts"],
        "description": "X's own GIF search, as the composer shows it. Read-only: nothing is typed into a post or sent. Pass a result's `url` (with your `query`) as `gif` on `POST /posts`.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "What to search, 2–40 characters.",
            "schema": {
              "type": "string"
            },
            "example": "ship it"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–24, default 12.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 24,
              "default": 12
            }
          }
        ],
        "responses": {
          "200": {
            "description": "GIFs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GifList"
                }
              }
            }
          },
          "422": {
            "description": "`errors/gif_search_unavailable` or `errors/gif_search_empty`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/search": {
      "get": {
        "operationId": "X_searchPosts",
        "summary": "Search posts",
        "tags": ["Search and reads"],
        "description": "The latest posts for a search, as the account sees them on X's Latest tab: newest first, reposts left out. Read-only.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "X search words and operators, up to 300 characters.",
            "schema": {
              "type": "string"
            },
            "example": "\"just launched\" min_faves:50"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–50, default 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Posts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          },
          "422": {
            "description": "`errors/search_not_loaded`: X showed neither posts nor its empty-results notice.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{post_id}": {
      "get": {
        "operationId": "X_getPost",
        "summary": "Retrieve a post",
        "tags": ["Posts"],
        "description": "One X post with its counts, read in the account's browser. `quote_counter`, `bookmark_counter` and `impressions_counter` are `null` when X's own data wasn't available and the page was read instead.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "post_id",
            "in": "path",
            "required": true,
            "description": "The post's id (its status digits).",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          }
        ],
        "responses": {
          "200": {
            "description": "The post.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                },
                "example": {
                  "object": "Post",
                  "provider": "X",
                  "id": "1850000000000000001",
                  "author": "Jane Demo",
                  "author_details": {
                    "id": "janedemo",
                    "public_identifier": "janedemo",
                    "profile_url": "https://x.com/janedemo",
                    "profile_picture_url": "https://pbs.twimg.com/profile_images/0/demo.jpg"
                  },
                  "date": "2026-11-06T09:12:00.000Z",
                  "text": "Shipping today.",
                  "share_url": "https://x.com/janedemo/status/1850000000000000001",
                  "reply_counter": 3,
                  "comment_counter": 3,
                  "reaction_counter": 12,
                  "repost_counter": 1,
                  "quote_counter": 0,
                  "bookmark_counter": 2,
                  "impressions_counter": 840,
                  "user_reacted": false
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_post_id`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/post_not_found`, or the account isn't found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "X_deletePost",
        "summary": "Delete a post",
        "tags": ["Posts"],
        "description": "Deletes one of the account's own posts or replies, through X's menu on it, then opens it again to check it's gone. Never someone else's post. Not paced.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "post_id",
            "in": "path",
            "required": true,
            "description": "The post's id.",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          }
        ],
        "responses": {
          "200": {
            "description": "Deleted, and checked gone.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "object": {
                      "const": "PostDeleted"
                    },
                    "post_id": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "403": {
            "description": "`errors/not_own_post`: not this account's post. Nothing was deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/post_not_found`: missing or already deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/delete_unavailable`: X's menu, its Delete item or the confirmation didn't show. Nothing was deleted.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: Delete was confirmed but the post may still be there. Open it before trying again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{post_id}/comments": {
      "post": {
        "operationId": "X_sendReply",
        "summary": "Reply to a post",
        "tags": ["Replies"],
        "description": "Replies under an X post (or under a reply, with `comment_id`) from the account's own X. If the post was edited, the reply goes under its latest version. Paced like posts; `answer: true` replies to someone who answered the account have their own 200 a day.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "post_id",
            "in": "path",
            "required": true,
            "description": "The post to reply under.",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "1–200 characters of `A-Z a-z 0-9 . _ : -`. The same key with the same request replays the first answer; see Write receipts.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["account_id", "text"],
                "properties": {
                  "account_id": {
                    "type": "string"
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 1250
                  },
                  "comment_id": {
                    "type": "string",
                    "pattern": "^[0-9]+$",
                    "description": "A reply's id (digits, as a string): the reply goes under it instead."
                  },
                  "answer": {
                    "type": "boolean",
                    "description": "This answers someone who replied to the account: counts toward the separate 200-a-day cap."
                  },
                  "navigation": {
                    "type": "string",
                    "enum": ["timeline", "direct"],
                    "description": "`timeline` finds the post in the account's Following feed first, as a person scrolling would, then falls back to its page; `direct` opens the post's page. Default: the post's page."
                  },
                  "author_handle": {
                    "type": "string",
                    "maxLength": 15,
                    "description": "The post author's X handle, which `timeline` looks for in the feed."
                  }
                }
              },
              "example": {
                "account_id": "janedemo",
                "text": "Congrats on the launch."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Replied.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommentSent"
                },
                "example": {
                  "object": "CommentSent",
                  "provider": "X",
                  "comment_id": "1850000000000000099",
                  "via": "timeline"
                }
              }
            }
          },
          "400": {
            "description": "Missing or invalid parameters or Idempotency-Key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`errors/in_progress` or `errors/account_busy`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/not_sent` (the browser stopped before Reply; `code` says why, e.g. `replies_limited` when the author limits who can reply), `errors/reply_button_disabled`, `errors/idempotency_key_reused`, `errors/x_app_not_loaded`, proxy errors.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`errors/too_fast`, `errors/daily_limit`, `errors/answers_daily_limit` or `errors/browser_busy`, with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: Reply was pressed but X didn't confirm. Read the receipt.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "X_listReplies",
        "summary": "List replies",
        "tags": ["Replies"],
        "description": "The replies an X post's page shows. `sort_by`: `MOST_RECENT` (the default) puts them newest first by `date`; `MOST_RELEVANT` keeps X's own order. `comment_id`: a reply's id, whose own replies come back instead. X's replies come in one page: a `cursor` answers `400 errors/invalid_parameters`, and every answer's `cursor` is `null`.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "post_id",
            "in": "path",
            "required": true,
            "description": "The post.",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Up to 100, default 50 on X.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "`MOST_RECENT` (default): newest first. `MOST_RELEVANT`: X's own order.",
            "schema": {
              "type": "string",
              "enum": ["MOST_RECENT", "MOST_RELEVANT"],
              "default": "MOST_RECENT"
            }
          },
          {
            "name": "comment_id",
            "in": "query",
            "required": false,
            "description": "A reply's id: its own replies come back instead.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Replies.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CommentList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters`: a `cursor` (X's replies come in one page), or an invalid `limit`, `sort_by` or `comment_id`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/reaction": {
      "post": {
        "operationId": "X_likePost",
        "summary": "Like a post",
        "tags": ["Likes, reposts and follows"],
        "description": "Likes one X post. To like a reply, pass its id as `comment_id` (or as `post_id`). A post the account already liked stays as it is (`already: true`). Not paced; no receipt.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["account_id", "post_id"],
                "properties": {
                  "account_id": {
                    "type": "string"
                  },
                  "post_id": {
                    "type": "string",
                    "pattern": "^[0-9]+$"
                  },
                  "reaction_type": {
                    "type": "string",
                    "enum": ["like"],
                    "default": "like",
                    "description": "X has only `like`."
                  },
                  "navigation": {
                    "type": "string",
                    "enum": ["timeline", "direct"],
                    "description": "`timeline` finds the post in the account's Following feed first, as a person scrolling would, then falls back to its page; `direct` opens the post's page. Default: the post's page."
                  },
                  "author_handle": {
                    "type": "string",
                    "maxLength": 15,
                    "description": "The post author's X handle, which `timeline` looks for in the feed."
                  },
                  "comment_id": {
                    "type": "string",
                    "pattern": "^[0-9]+$",
                    "description": "A reply's id: that reply is liked."
                  }
                }
              },
              "example": {
                "account_id": "janedemo",
                "post_id": "1850000000000000001"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Liked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactionAdded"
                }
              }
            }
          },
          "400": {
            "description": "`errors/unsupported_reaction` or invalid parameters.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/post_not_found`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/like_unavailable` or `errors/like_not_kept` (X undid the like).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/like_unconfirmed`: open the post before liking again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/repost": {
      "post": {
        "operationId": "X_repostPost",
        "summary": "Repost a post, or undo a repost",
        "tags": ["Likes, reposts and follows"],
        "description": "A plain repost of one X post. A post the account already reposted stays as it is (`already: true`). With `undo: true`, takes the account's repost of that post back instead: X's green Repost button, then **Undo repost**, answered once the post shows its plain Repost button (`PostUnreposted`; a post it hasn't reposted answers `already: true` with nothing pressed). An undo's receipt fingerprint differs from the repost's, so one key never covers both. Not paced.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. With a key, the write gets a receipt (`GET /writes/{key}`) and a repeat replays the first answer.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["account_id", "post_id"],
                "properties": {
                  "account_id": {
                    "type": "string"
                  },
                  "post_id": {
                    "type": "string",
                    "pattern": "^[0-9]+$",
                    "description": "The post to repost, or (with `undo`) the post the account reposted."
                  },
                  "navigation": {
                    "type": "string",
                    "enum": ["timeline", "direct"],
                    "description": "`timeline` finds the post in the account's Following feed first, as a person scrolling would, then falls back to its page; `direct` opens the post's page. Default: the post's page."
                  },
                  "author_handle": {
                    "type": "string",
                    "maxLength": 15,
                    "description": "The post author's X handle, which `timeline` looks for in the feed."
                  },
                  "undo": {
                    "type": "boolean",
                    "default": false,
                    "description": "`true` takes the account's repost back. `true` or `false` only: any other value answers `400`. X only (a LinkedIn post answers `501`)."
                  }
                }
              },
              "examples": {
                "repost": {
                  "value": {
                    "account_id": "janedemo",
                    "post_id": "1850000000000000001"
                  }
                },
                "undo": {
                  "value": {
                    "account_id": "janedemo",
                    "post_id": "1850000000000000001",
                    "undo": true
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reposted, or (with `undo`) the repost taken back.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PostReposted"
                    },
                    {
                      "$ref": "#/components/schemas/PostUnreposted"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters`: no X post id, or `undo` that isn't `true` or `false`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/post_not_found`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/repost_unavailable` (X didn't offer Repost, or Undo repost), `errors/not_reposted` or `errors/not_unreposted`. Nothing changed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "`errors/feature_not_implemented`: `undo` on a LinkedIn post.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/repost_unconfirmed`: check the post; doing it again changes nothing.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/posts/{post_id}/reactions": {
      "get": {
        "operationId": "X_listLikers",
        "summary": "List likers",
        "tags": ["Likes, reposts and follows"],
        "description": "Who liked one of the account's own posts. X shows a post's likers to its author only. Read-only.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "post_id",
            "in": "path",
            "required": true,
            "description": "One of the account's own posts.",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–200, default 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Likers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReactionList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/follow": {
      "post": {
        "operationId": "X_followUser",
        "summary": "Follow an account",
        "tags": ["Likes, reposts and follows"],
        "description": "Follows one X account. An account already followed (or asked to follow) stays as it is (`already: true`). Not paced. There is no unfollow.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. With a key, the write gets a receipt (`GET /writes/{key}`) and a repeat replays the first answer.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["account_id", "identifier"],
                "properties": {
                  "account_id": {
                    "type": "string"
                  },
                  "identifier": {
                    "type": "string",
                    "pattern": "^@?[A-Za-z0-9_]{1,15}$",
                    "description": "The X handle to follow, with or without `@`."
                  }
                }
              },
              "example": {
                "account_id": "janedemo",
                "identifier": "@marclou"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Followed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserFollowed"
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters` or `errors/cannot_follow_self`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/user_not_found`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/profile_not_loaded`, `errors/follow_unavailable` or `errors/follow_not_kept`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`errors/follow_limited`: X says the account can't follow more people right now.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/follow_unconfirmed`: check the profile; following again changes nothing.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/followers": {
      "get": {
        "operationId": "X_listFollowers",
        "summary": "List followers",
        "tags": ["Likes, reposts and follows"],
        "description": "The account's own newest X followers, newest first. Read-only.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–1000, default 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Followers.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserFollowerList"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/{identifier}/posts": {
      "get": {
        "operationId": "X_listUserPosts",
        "summary": "List a profile's posts",
        "tags": ["Search and reads"],
        "description": "An X profile's newest posts, reposts left out. It comes in one page: a `cursor` answers `400 errors/invalid_parameters`, and the answer's `cursor` is always `null`; an empty list means no post showed within 25 seconds.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "identifier",
            "in": "path",
            "required": true,
            "description": "The X handle (with or without `@`).",
            "schema": {
              "type": "string"
            },
            "example": "marclou"
          },
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default 20, at most 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Posts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostList"
                }
              }
            }
          },
          "404": {
            "description": "`errors/user_not_found`, or the account isn't found.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters`: a `cursor` (X lists come in one page).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/me/posts": {
      "get": {
        "operationId": "X_listOwnPosts",
        "summary": "List the account's own posts",
        "tags": ["Search and reads"],
        "description": "The account's own posts, replies or reposts, newest first, from its profile's tabs: what a rebrand deletes (`DELETE /posts/{post_id}`) or undoes (`POST /posts/repost` with `undo: true` and the item's `reposted_id`). X's own data first; when it can't be had, the tab itself, read while it's scrolled like a person. Nothing is clicked. On a LinkedIn account this is `/users/{identifier}/posts`.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "`posts` (the Posts tab: the account's posts, the pinned one marked `pinned`), `replies` (the Replies tab: its replies, each with `in_reply_to`) or `reposts` (each with `reposted_id`).",
            "schema": {
              "type": "string",
              "enum": ["posts", "replies", "reposts"],
              "default": "posts"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1–100, default 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "The previous page's `cursor`. It still works once you deleted the post it names: the page goes on from the older ones.",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]{1,25}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The items, and the next page's cursor (`null` at the end).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OwnPostList"
                },
                "example": {
                  "object": "OwnPostList",
                  "provider": "X",
                  "account_id": "11111111-1111-4111-8111-111111111111",
                  "kind": "reposts",
                  "items": [
                    {
                      "object": "OwnPost",
                      "id": "1850000000000000003",
                      "kind": "repost",
                      "text": "Shipped my app",
                      "created_at": "2026-11-07T09:00:00.000Z",
                      "reposted_id": "1700000000000000009"
                    }
                  ],
                  "cursor": "1850000000000000003"
                }
              }
            }
          },
          "400": {
            "description": "`errors/missing_parameters` or `errors/invalid_parameters`: a `kind`, `limit` or `cursor` it doesn't take.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/timeline_not_loaded`: the profile showed neither posts nor its empty notice (never an empty list), or `errors/x_app_not_loaded`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: nothing was changed; try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/me": {
      "get": {
        "operationId": "X_getOwnProfile",
        "summary": "Retrieve the profile",
        "tags": ["Profile and analytics"],
        "description": "The account's own X profile as X's Edit profile window and Change username page show it (Unipile's `AccountOwnerProfile` fields where it has them). The browser reads them and presses nothing: it's a dry run of the edit. Empty fields are `null`. When X shows another handle than Lempile has on record, the record follows. On a LinkedIn account this is LinkedIn's own profile read.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "query",
            "required": true,
            "description": "The connected X account: its Lempile id, its X user id, or its handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          }
        ],
        "responses": {
          "200": {
            "description": "The profile.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountOwnerProfile"
                },
                "example": {
                  "object": "AccountOwnerProfile",
                  "provider": "X",
                  "account_id": "11111111-1111-4111-8111-111111111111",
                  "name": "LAUNCH WIRE",
                  "username": "launchwire",
                  "public_identifier": "launchwire",
                  "public_profile_url": "https://x.com/launchwire",
                  "bio": "Every launch worth knowing, as it ships.",
                  "location": null,
                  "website": "https://launchwire.example",
                  "profile_picture_url": "https://pbs.twimg.com/profile_images/2/new.jpg",
                  "cover_picture_url": "https://pbs.twimg.com/profile_banners/9/1700000000",
                  "can_change_username": true
                }
              }
            }
          },
          "422": {
            "description": "`errors/profile_field_not_found` or `errors/x_app_not_loaded`: X's Edit profile didn't show.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: nothing was changed; try again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/users/me/edit": {
      "patch": {
        "operationId": "X_editProfile",
        "summary": "Edit the profile",
        "tags": ["Profile and analytics"],
        "description": "Unipile's \"Edit own profile\" for an X account: `name`, `bio`, `location`, `website`, `avatar`, `banner` and `username`, any of them (the others stay as they are). `POST` works too.\n\nThe browser reads X's Edit profile, gives it the pictures (through X's crop window, as is), types each field that isn't already as asked, checks the others unchanged, presses Save and reads everything back on a fresh window; the handle comes last, on X's Change username page, checked free, saved and read back. On a verified account a new name, avatar or handle removes the checkmark until X reviews it again: X asks at Save, and Lempile confirms that notice. After a new handle, Lempile's record of the account follows in the same request.\n\nWith `website` alone the answer is the Website edit's, as it has been since Nov 3 2026: `{ website, previous_website, already }`, or `{ website, would }` for a dry run.\n\nPictures and a handle can take a few minutes: the request waits 140 seconds, then answers `504 errors/timeout` while the browser goes on (up to 10 minutes); send an `Idempotency-Key` and read `GET /writes/{key}`.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. With a key, the write gets a receipt (`GET /writes/{key}`) and a repeat replays the first answer.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": ["account_id"],
                "properties": {
                  "account_id": {
                    "type": "string",
                    "description": "Body only."
                  },
                  "type": {
                    "type": "string",
                    "enum": ["X", "TWITTER"]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "description": "One line. Counted as X counts it (an emoji is 2)."
                  },
                  "bio": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Line breaks kept; `\"\"` clears it. Unipile's `summary` is taken too."
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 30,
                    "description": "One line; `\"\"` clears it. Words, not Unipile's LinkedIn place id."
                  },
                  "website": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 100,
                    "description": "One https address, a host with a dot, no spaces or credentials. It can't be emptied."
                  },
                  "username": {
                    "type": "string",
                    "pattern": "^@?[A-Za-z0-9_]{4,15}$",
                    "description": "The new handle, with or without `@`. It comes last, on X's Change username page."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "Reads every window and answers `ProfileEditDryRun`: nothing is given, typed or pressed. `true` or `false` only."
                  },
                  "avatar": {
                    "type": "string",
                    "format": "binary",
                    "description": "A JPEG or PNG of at most 2 MB. Unipile's `picture` is taken too."
                  },
                  "banner": {
                    "type": "string",
                    "format": "binary",
                    "description": "The header photo: a JPEG or PNG of at most 5 MB. Unipile's `cover_picture` is taken too."
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["account_id"],
                "properties": {
                  "account_id": {
                    "type": "string",
                    "description": "Body only."
                  },
                  "type": {
                    "type": "string",
                    "enum": ["X", "TWITTER"]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "description": "One line. Counted as X counts it (an emoji is 2)."
                  },
                  "bio": {
                    "type": "string",
                    "maxLength": 160,
                    "description": "Line breaks kept; `\"\"` clears it. Unipile's `summary` is taken too."
                  },
                  "location": {
                    "type": "string",
                    "maxLength": 30,
                    "description": "One line; `\"\"` clears it. Words, not Unipile's LinkedIn place id."
                  },
                  "website": {
                    "type": "string",
                    "format": "uri",
                    "maxLength": 100,
                    "description": "One https address, a host with a dot, no spaces or credentials. It can't be emptied."
                  },
                  "custom_link": {
                    "type": "object",
                    "properties": {
                      "url": {
                        "type": "string"
                      },
                      "type": {
                        "const": "WEBSITE"
                      }
                    },
                    "description": "Unipile's form of `website`; must match it when both are given."
                  },
                  "username": {
                    "type": "string",
                    "pattern": "^@?[A-Za-z0-9_]{4,15}$",
                    "description": "The new handle, with or without `@`. It comes last, on X's Change username page."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "Reads every window and answers `ProfileEditDryRun`: nothing is given, typed or pressed. `true` or `false` only."
                  },
                  "avatar": {
                    "$ref": "#/components/schemas/ProfilePicture",
                    "description": "At most 2 MB. Unipile's `picture` is taken too."
                  },
                  "banner": {
                    "$ref": "#/components/schemas/ProfilePicture",
                    "description": "The header photo, at most 5 MB. Unipile's `cover_picture` is taken too."
                  }
                }
              },
              "examples": {
                "website": {
                  "summary": "The website alone",
                  "value": {
                    "account_id": "janedemo",
                    "type": "X",
                    "website": "https://example.com/?ref=x"
                  }
                },
                "rebrand": {
                  "summary": "A rebrand",
                  "value": {
                    "account_id": "janedemo",
                    "name": "LAUNCH WIRE",
                    "bio": "Every launch worth knowing, as it ships.",
                    "location": "",
                    "username": "@launchwire",
                    "avatar": {
                      "name": "avatar.png",
                      "content_type": "image/png",
                      "data_base64": "iVBORw0KGgo…"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Saved and read back, or a dry run.",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/ProfileEdited"
                    },
                    {
                      "$ref": "#/components/schemas/ProfileEditDryRun"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters` or the browser's `errors/invalid_*`: a field X wouldn't take (a picture that isn't a JPEG or PNG, is empty, isn't valid base64 or is too large; a handle that isn't 4–15 letters, digits or `_`; `dry_run` that isn't `true` or `false`…). Nothing was changed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`errors/password_required`: X asks for the account's password to change the handle; Lempile never types it. `errors/insufficient_permissions`: the key lacks `accounts.write`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`errors/username_taken`: X says the handle isn't free. `errors/in_progress`: the same key is still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/username_field_not_found` (no Username field on X's Change username page, as while an X Premium check is under review), `errors/username_refused`, `errors/username_check_failed`, `errors/username_not_kept`, `errors/profile_photo_input_not_found`, `errors/profile_photo_not_taken`, `errors/profile_field_not_found`, `errors/typing_failed`, `errors/profile_fields_changed`, `errors/profile_save_unavailable`, `errors/profile_value_not_kept` (`detail` quotes what X said) or `errors/idempotency_key_reused`. A refusal after the Edit profile part was saved carries `done`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "501": {
            "description": "`errors/feature_not_implemented`: a field an X profile doesn't have, another `type`, or a LinkedIn account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/profile_unconfirmed` or `errors/username_unconfirmed`: saved but not read back. Read the profile before trying again.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: still running, or not sure. Read the receipt.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{account_id}/posts/{status_id}/pin": {
      "post": {
        "operationId": "X_pinPost",
        "summary": "Pin a post",
        "tags": ["Posts"],
        "description": "Pins one of the account's own posts to its profile. X keeps one pinned post: a new pin replaces it (`previous_pinned_id`). Answers only once the profile shows it. `{\"dry_run\": true}` opens X's menu, reads it and closes it.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "path",
            "required": true,
            "description": "Lempile id, X user id or handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "status_id",
            "in": "path",
            "required": true,
            "description": "The post's id (5–25 digits).",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. With a key, the write gets a receipt (`GET /writes/{key}`) and a repeat replays the first answer.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "dry_run": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done, or already so.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostPin"
                },
                "example": {
                  "object": "PostPin",
                  "provider": "X",
                  "status": "pinned",
                  "status_id": "1850000000000000001",
                  "previous_pinned_id": "1840000000000000002",
                  "already": false
                }
              }
            }
          },
          "400": {
            "description": "`errors/not_own_post`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/post_not_found`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/pin_unavailable` or `errors/profile_not_loaded`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/pin_unconfirmed`: check the profile.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{account_id}/posts/{status_id}/unpin": {
      "post": {
        "operationId": "X_unpinPost",
        "summary": "Unpin a post",
        "tags": ["Posts"],
        "description": "Unpins the account's pinned post. Answers only once the profile shows it. `{\"dry_run\": true}` opens X's menu, reads it and closes it.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "path",
            "required": true,
            "description": "Lempile id, X user id or handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "status_id",
            "in": "path",
            "required": true,
            "description": "The post's id (5–25 digits).",
            "schema": {
              "type": "string"
            },
            "example": "1850000000000000001"
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Optional. With a key, the write gets a receipt (`GET /writes/{key}`) and a repeat replays the first answer.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "dry_run": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Done, or already so.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PostPin"
                },
                "example": {
                  "object": "PostPin",
                  "provider": "X",
                  "status": "unpinned",
                  "status_id": "1850000000000000001",
                  "previous_pinned_id": "1850000000000000001",
                  "already": false
                }
              }
            }
          },
          "400": {
            "description": "`errors/not_own_post`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/post_not_found`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/pin_unavailable` or `errors/profile_not_loaded`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/pin_unconfirmed`: check the profile.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{account_id}/analytics": {
      "get": {
        "operationId": "X_getAnalytics",
        "summary": "Retrieve analytics",
        "tags": ["Profile and analytics"],
        "description": "The X account's own analytics by UTC day, read from its analytics page (x.com/i/account_analytics, which needs X Premium). Complete days only: `to` is capped at yesterday (UTC). Each count is X's daily series; `engagements`, `engagement_rate` and `shares` are always `null` (X has them by the hour only). Read-only.\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "path",
            "required": true,
            "description": "Lempile id, X user id or handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "First day, `YYYY-MM-DD`.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-10-01"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "Last day, `YYYY-MM-DD`; at most 365 days after `from`.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-10-31"
          }
        ],
        "responses": {
          "200": {
            "description": "Analytics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountAnalytics"
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/analytics_unavailable`: X doesn't show analytics to this account yet (e.g. under X's follower floor).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "502": {
            "description": "`errors/analytics_not_loaded` (no Premium, or the page didn't finish) or `errors/analytics_failed`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/accounts/{account_id}/capture": {
      "post": {
        "operationId": "X_capturePage",
        "summary": "Capture a page",
        "tags": ["Page capture"],
        "description": "A JPEG of one page, opened in the X account's own browser and proxy. Read-only: a new tab, cookie banners and X's overlays hidden with CSS (never clicked), the picture, the tab closed. Not a write: no `Idempotency-Key`, no receipt, not paced.\n\nIt opens only:\n\n- **A public X post**, exactly `https://x.com/<handle>/status/<digits>` (handle 1–15 letters, digits or `_`, not `i`; 1–25 digits; no query, fragment or trailing slash; `x.com` only). The picture is the post's own article, read from the account's own signed-in X, taken only when X shows it under that handle, ending at its action bar. No `clip.selector`; with `x_post: { counts: false }` the time and views row and the action bar are left out too.\n- **A status page**: `https://<host>`, `https://<host>/` or `https://<host>/incidents/<id>` (8–40 letters or digits) on `www.vercel-status.com`, `www.githubstatus.com`, `status.supabase.com`, `www.cloudflarestatus.com`, `status.openai.com`, `status.claude.com`, `www.netlifystatus.com`, `status.render.com`, `status.flyio.net`, `status.clerk.com`, `resend-status.com`.\n- **The account's own X**: `https://x.com/<its handle>` and `https://x.com/i/account_analytics`.\n- **News pages**: any page on `blog.google`, `developers.google.com`, `blogs.bing.com`, `www.seroundtable.com`, `techcrunch.com`; `https://news.ycombinator.com/item?id=<digits>`; and any page on a site Lempile added to your workspace's list.\n\nHosts match exactly. The browser checks the address again before opening it and after the page loads. When the page gave no picture the answer is still `200`, with `ok: false` and the browser's `code`.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "account_id",
            "in": "path",
            "required": true,
            "description": "Lempile id, X user id or handle.",
            "schema": {
              "type": "string"
            },
            "example": "janedemo"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageCaptureRequest"
              },
              "examples": {
                "post": {
                  "summary": "A public X post",
                  "value": {
                    "url": "https://x.com/OpenAI/status/1986000000000000001",
                    "width": 520,
                    "dpr": 2
                  }
                },
                "post_no_counts": {
                  "summary": "A public X post without its counts",
                  "value": {
                    "url": "https://x.com/OpenAI/status/1986000000000000001",
                    "width": 520,
                    "dpr": 2,
                    "x_post": {
                      "counts": false
                    }
                  }
                },
                "status": {
                  "summary": "An incident's page",
                  "value": {
                    "url": "https://status.claude.com/incidents/phg1y2yh07n2",
                    "width": 1024,
                    "dpr": 2,
                    "clip": {
                      "maxHeight": 1400
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The picture (`ok: true`), or why there is none (`ok: false` with `code`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageCapture"
                },
                "example": {
                  "object": "PageCapture",
                  "ok": true,
                  "account_id": "11111111-1111-4111-8111-111111111111",
                  "url": "https://x.com/OpenAI/status/1986000000000000001",
                  "final_url": "https://x.com/OpenAI/status/1986000000000000001",
                  "title": "OpenAI on X: \"…\" / X",
                  "width": 1040,
                  "height": 1224,
                  "jpeg_base64": "/9j/4AAQSkZJRg…",
                  "captured_at": "2026-11-07T18:20:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "`errors/invalid_parameters`: an address it doesn't open (the detail lists them), a field out of range, or `clip.selector` on an X post. `errors/missing_parameters`: no `url`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`errors/insufficient_permissions`: the key lacks `accounts.write`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`errors/proxy_auth_failed` or `errors/proxy_unreachable`: the account's proxy is down.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "504": {
            "description": "`errors/timeout`: no picture within 90 seconds. Nothing was clicked or typed.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/articles": {
      "post": {
        "operationId": "X_createArticle",
        "summary": "Publish an Article",
        "tags": ["Articles"],
        "description": "Builds one X Article in a new draft (title, every block in order, cover), reads the draft back, and publishes it only if X kept exactly those blocks; otherwise nothing is published and the draft stays in the account's Drafts. It takes minutes, so this answers `202` and `GET /articles/{key}` says where it is. The same key never builds twice. Paced like posts unless `dry_run`.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "description": "1–200 characters of `A-Z a-z 0-9 . _ : -`. The same key with the same request replays the first answer; see Write receipts.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ArticleRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Building.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticleJob"
                },
                "example": {
                  "object": "ArticleJob",
                  "id": "article-2026-11-07",
                  "account_id": "11111111-1111-4111-8111-111111111111",
                  "status": "building",
                  "detail": "Starting."
                }
              }
            }
          },
          "400": {
            "description": "Invalid body or Idempotency-Key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "`account_busy`: another Article is building on this account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "`not_sent`: nothing was published; `code` and `detail` say why.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "`errors/too_fast` or `errors/daily_limit`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "`errors/resource_not_found`: no such account in this workspace, or it isn't an X account.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "423": {
            "description": "`errors/x_account_locked`: X shows the account its lock page (x.com/account/access). Nothing was done; someone has to pass X's check.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "503": {
            "description": "`errors/service_unavailable` (the account isn't ready, or the browser runner can't be reached), `errors/no_client_session`, or `errors/maintenance` with `retry_at`.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/articles/{key}": {
      "get": {
        "operationId": "X_getArticle",
        "summary": "Retrieve an Article job",
        "tags": ["Articles"],
        "description": "Where one Article is, by the `Idempotency-Key` it was sent with: `building` (202), `published` (200, `url`, `article_id`), `draft` (200, a dry run, `draft_url`), `not_sent` (422, or 409 for `account_busy`) or `unknown` (200: Publish was pressed but X didn't confirm; check the account's Articles before sending again).\n\nScope: `accounts.read`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "The Idempotency-Key the Article was sent with.",
            "schema": {
              "type": "string"
            },
            "example": "article-2026-11-07"
          }
        ],
        "responses": {
          "200": {
            "description": "Published, draft or unknown.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticleJob"
                }
              }
            }
          },
          "202": {
            "description": "Still building.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticleJob"
                }
              }
            }
          },
          "404": {
            "description": "`errors/not_found`: no Article with this key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Not sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ArticleJob"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/writes/{key}": {
      "get": {
        "operationId": "X_getWrite",
        "summary": "Retrieve a write receipt",
        "tags": ["Write receipts"],
        "description": "What became of one write sent with an `Idempotency-Key` (`POST /posts`, replies, and follows, reposts, pins and profile edits sent with a key). `state` is `done` (sent: `response` is the stored answer), `failed` (nothing was sent), `pending` (still running, or not sure) or `none`. The browser's answer is kept 48 hours, also after the request stopped waiting.\n\nScope: `accounts.read` or `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "The write's Idempotency-Key.",
            "schema": {
              "type": "string"
            },
            "example": "post-2026-11-07-01"
          }
        ],
        "responses": {
          "200": {
            "description": "The receipt.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteStatus"
                },
                "example": {
                  "object": "WriteStatus",
                  "key": "post-2026-11-07-01",
                  "state": "done",
                  "status": 201,
                  "response": {
                    "object": "PostCreated",
                    "provider": "X",
                    "post_id": "1850000000000000001"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "`insufficient_permissions`: the key has neither `accounts.read` nor `accounts.write`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/writes/{key}/not-sent": {
      "post": {
        "operationId": "X_releaseWrite",
        "summary": "Mark a write not sent",
        "tags": ["Write receipts"],
        "description": "After you checked on X that a pending write isn't there: marks it not sent, so the key can be sent again and it stops counting toward the pace. A write Lempile has as sent stays sent (`409`), and one under 5 minutes old or still running answers `409`.\n\nScope: `accounts.write`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "The write's Idempotency-Key.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Marked not sent (or already not sent).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteStatus"
                }
              }
            }
          },
          "404": {
            "description": "No write with this key.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "Sent, too recent, or still running.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key (`{error, message}`), `errors/disconnected_account`, or `errors/reauth_required` when X is signed out in the account's browser.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "402": {
            "description": "`subscription_required`: the workspace has no active trial or subscription.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-KEY"
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "example": "errors/not_sent"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "retry_at": {
            "type": "string",
            "format": "date-time"
          },
          "code": {
            "type": "string",
            "description": "The browser's own reason, when it refused before the click: `replies_limited`, `post_not_accepted`, `gif_not_found`, `browser_busy`…"
          }
        },
        "required": ["type", "status"]
      },
      "Account": {
        "type": "object",
        "properties": {
          "object": {
            "const": "Account"
          },
          "id": {
            "type": "string"
          },
          "type": {
            "const": "X"
          },
          "name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "enum": ["OK", "CREDENTIALS", "CONNECTING", "ERROR"]
                }
              }
            }
          }
        }
      },
      "AccountList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "list"
          },
          "count": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "provider": {
                  "type": "string",
                  "example": "x"
                },
                "display_name": {
                  "type": "string"
                },
                "external_account_id": {
                  "type": "string"
                },
                "public_identifier": {
                  "type": "string",
                  "description": "The X handle."
                },
                "username": {
                  "type": "string"
                },
                "profile_url": {
                  "type": "string"
                },
                "profile_picture_url": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "connected_at": {
                  "type": "string"
                },
                "created_at": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "AuthorDetails": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "public_identifier": {
            "type": "string"
          },
          "profile_url": {
            "type": "string"
          },
          "profile_picture_url": {
            "type": "string"
          }
        }
      },
      "Post": {
        "type": "object",
        "properties": {
          "object": {
            "const": "Post"
          },
          "provider": {
            "const": "X"
          },
          "id": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "author_details": {
            "$ref": "#/components/schemas/AuthorDetails"
          },
          "date": {
            "type": "string",
            "format": "date-time"
          },
          "text": {
            "type": "string"
          },
          "share_url": {
            "type": "string"
          },
          "reply_counter": {
            "type": "integer"
          },
          "comment_counter": {
            "type": "integer"
          },
          "reaction_counter": {
            "type": "integer"
          },
          "repost_counter": {
            "type": "integer"
          },
          "quote_counter": {
            "type": ["integer", "null"]
          },
          "bookmark_counter": {
            "type": ["integer", "null"]
          },
          "impressions_counter": {
            "type": ["integer", "null"]
          },
          "user_reacted": {
            "type": "boolean"
          }
        }
      },
      "PostList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "PostList"
          },
          "provider": {
            "const": "X"
          },
          "query": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Post"
            }
          },
          "cursor": {
            "type": "null"
          }
        }
      },
      "PostCreated": {
        "type": "object",
        "properties": {
          "object": {
            "const": "PostCreated"
          },
          "provider": {
            "const": "X"
          },
          "post_id": {
            "type": "string"
          }
        }
      },
      "PostDryRun": {
        "type": "object",
        "properties": {
          "object": {
            "const": "PostDryRun"
          },
          "provider": {
            "const": "X"
          },
          "not_sent": {
            "const": true
          },
          "gif": {
            "type": "object"
          }
        }
      },
      "GifList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "GifList"
          },
          "provider": {
            "const": "X"
          },
          "query": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "title": {
                  "type": "string"
                },
                "width": {
                  "type": "integer"
                },
                "height": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "CommentSent": {
        "type": "object",
        "properties": {
          "object": {
            "const": "CommentSent"
          },
          "provider": {
            "const": "X"
          },
          "comment_id": {
            "type": ["string", "null"],
            "description": "`null` when X gave no link; the reply still went out."
          },
          "via": {
            "type": "string",
            "enum": ["timeline", "direct"]
          },
          "edited_from": {
            "type": "string",
            "description": "When the post was edited: the id the reply was asked for."
          }
        }
      },
      "CommentList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "CommentList"
          },
          "items": {
            "type": "array",
            "items": {
              "allOf": [
                {
                  "$ref": "#/components/schemas/Post"
                },
                {
                  "type": "object",
                  "properties": {
                    "object": {
                      "const": "Comment"
                    },
                    "post_id": {
                      "type": "string"
                    }
                  }
                }
              ]
            }
          },
          "cursor": {
            "type": "null"
          },
          "total_items": {
            "type": "integer"
          }
        }
      },
      "ReactionAdded": {
        "type": "object",
        "properties": {
          "object": {
            "const": "ReactionAdded"
          },
          "provider": {
            "const": "X"
          },
          "post_id": {
            "type": "string"
          },
          "reaction_type": {
            "const": "like"
          },
          "already": {
            "type": "boolean"
          },
          "via": {
            "type": "string"
          }
        }
      },
      "PostReposted": {
        "type": "object",
        "properties": {
          "object": {
            "const": "PostReposted"
          },
          "provider": {
            "const": "X"
          },
          "post_id": {
            "type": "string"
          },
          "already": {
            "type": "boolean"
          },
          "via": {
            "type": "string"
          }
        }
      },
      "OwnPost": {
        "type": "object",
        "properties": {
          "object": {
            "const": "OwnPost"
          },
          "id": {
            "type": "string",
            "description": "The post, reply or repost itself (a repost's own id)."
          },
          "kind": {
            "type": "string",
            "enum": ["post", "reply", "repost"]
          },
          "text": {
            "type": "string",
            "description": "Its words; a repost's are the reposted post's."
          },
          "created_at": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "reposted_id": {
            "type": "string",
            "description": "A repost: the post it reposted, which `POST /posts/repost` with `undo: true` takes."
          },
          "in_reply_to": {
            "type": "string",
            "description": "A reply: the post it answers."
          },
          "pinned": {
            "const": true,
            "description": "The profile's pinned post (first page only)."
          }
        }
      },
      "OwnPostList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "OwnPostList"
          },
          "provider": {
            "const": "X"
          },
          "account_id": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": ["posts", "replies", "reposts"]
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OwnPost"
            }
          },
          "cursor": {
            "type": ["string", "null"],
            "description": "Pass it back as `cursor` for the next page; `null` at the end."
          }
        }
      },
      "PostUnreposted": {
        "type": "object",
        "properties": {
          "object": {
            "const": "PostUnreposted"
          },
          "provider": {
            "const": "X"
          },
          "post_id": {
            "type": "string"
          },
          "already": {
            "type": "boolean",
            "description": "`true`: the account hadn't reposted it; nothing was pressed."
          },
          "via": {
            "type": "string"
          }
        }
      },
      "ReactionList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "ReactionList"
          },
          "provider": {
            "const": "X"
          },
          "post_id": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "const": "Reaction"
                },
                "value": {
                  "const": "LIKE"
                },
                "author": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "public_identifier": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "profile_url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "cursor": {
            "type": "null"
          },
          "total_items": {
            "type": "integer"
          }
        }
      },
      "UserFollowed": {
        "type": "object",
        "properties": {
          "object": {
            "const": "UserFollowed"
          },
          "provider": {
            "const": "X"
          },
          "identifier": {
            "type": "string"
          },
          "already": {
            "type": "boolean"
          }
        }
      },
      "UserFollowerList": {
        "type": "object",
        "properties": {
          "object": {
            "const": "UserFollowerList"
          },
          "provider": {
            "const": "X"
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "object": {
                  "const": "UserFollower"
                },
                "id": {
                  "type": "string"
                },
                "public_identifier": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "profile_url": {
                  "type": "string"
                }
              }
            }
          },
          "cursor": {
            "type": "null"
          }
        }
      },
      "ProfileEdited": {
        "type": "object",
        "properties": {
          "object": {
            "const": "ProfileEdited"
          },
          "provider": {
            "const": "X"
          },
          "account_id": {
            "type": "string"
          },
          "changed": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "What X keeps now, read back on fresh pages: each field changed (`name`, `bio`, `location`, `website`, `avatar` and `banner` as the addresses X serves them from, `username`)."
          },
          "previous": {
            "type": "object",
            "additionalProperties": {
              "type": ["string", "null"]
            },
            "description": "What those fields were."
          },
          "already": {
            "type": ["array", "boolean"],
            "items": {
              "type": "string"
            },
            "description": "The fields that were already as asked (nothing typed for them). A website edit: `true` when the address was already set."
          },
          "avatar_changed": {
            "type": ["boolean", "null"]
          },
          "banner_changed": {
            "type": ["boolean", "null"]
          },
          "username": {
            "type": "string",
            "description": "The handle X shows, when one was asked."
          },
          "website": {
            "type": ["string", "null"],
            "description": "A website edit: the address X keeps."
          },
          "previous_website": {
            "type": ["string", "null"],
            "description": "A website edit: the one before."
          }
        }
      },
      "ProfileEditDryRun": {
        "type": "object",
        "properties": {
          "object": {
            "const": "ProfileEditDryRun"
          },
          "provider": {
            "const": "X"
          },
          "not_sent": {
            "const": true
          },
          "current": {
            "type": "object",
            "additionalProperties": {
              "type": ["string", "null"]
            },
            "description": "What each field asked for shows now."
          },
          "would_change": {
            "type": "object",
            "description": "The fields Save would change (a picture always: `\"new picture\"`)."
          },
          "already": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "checks": {
            "type": "object",
            "properties": {
              "save_button": {
                "type": "boolean"
              },
              "photo_inputs": {
                "type": "object"
              },
              "username_field": {
                "type": "boolean"
              },
              "password_required": {
                "type": "boolean"
              }
            }
          },
          "website": {
            "type": ["string", "null"],
            "description": "A website dry run: the address shown now."
          },
          "would": {
            "type": "string",
            "enum": ["set", "already_set"],
            "description": "A website dry run."
          }
        }
      },
      "ProfilePicture": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "content_type": {
            "type": "string",
            "enum": ["image/jpeg", "image/png"],
            "description": "Optional: the type is read from the file's bytes."
          },
          "data_base64": {
            "type": "string",
            "description": "The file's bytes in base64, no `data:` prefix."
          }
        },
        "required": ["data_base64"]
      },
      "AccountOwnerProfile": {
        "type": "object",
        "properties": {
          "object": {
            "const": "AccountOwnerProfile"
          },
          "provider": {
            "const": "X"
          },
          "account_id": {
            "type": "string"
          },
          "name": {
            "type": ["string", "null"]
          },
          "username": {
            "type": ["string", "null"]
          },
          "public_identifier": {
            "type": ["string", "null"]
          },
          "public_profile_url": {
            "type": ["string", "null"]
          },
          "bio": {
            "type": ["string", "null"]
          },
          "location": {
            "type": ["string", "null"]
          },
          "website": {
            "type": ["string", "null"]
          },
          "profile_picture_url": {
            "type": ["string", "null"]
          },
          "cover_picture_url": {
            "type": ["string", "null"]
          },
          "can_change_username": {
            "type": ["boolean", "null"],
            "description": "`false` when X's Change username page shows no Username field or asks for the password."
          }
        }
      },
      "PostPin": {
        "type": "object",
        "properties": {
          "object": {
            "type": "string",
            "enum": ["PostPin", "PostPinDryRun"]
          },
          "provider": {
            "const": "X"
          },
          "status": {
            "type": "string",
            "enum": ["pinned", "unpinned", "already_pinned", "already_unpinned"]
          },
          "status_id": {
            "type": "string"
          },
          "previous_pinned_id": {
            "type": ["string", "null"]
          },
          "already": {
            "type": "boolean"
          },
          "would": {
            "type": "string"
          },
          "not_sent": {
            "type": "boolean"
          }
        }
      },
      "AnalyticsDay": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "impressions": {
            "type": ["integer", "null"]
          },
          "likes": {
            "type": ["integer", "null"]
          },
          "replies": {
            "type": ["integer", "null"]
          },
          "reposts": {
            "type": ["integer", "null"]
          },
          "quotes": {
            "type": ["integer", "null"]
          },
          "bookmarks": {
            "type": ["integer", "null"]
          },
          "profile_visits": {
            "type": ["integer", "null"]
          },
          "posts": {
            "type": ["integer", "null"]
          },
          "replies_sent": {
            "type": ["integer", "null"]
          },
          "quotes_sent": {
            "type": ["integer", "null"]
          },
          "new_follows": {
            "type": ["integer", "null"]
          },
          "unfollows": {
            "type": ["integer", "null"]
          },
          "engagements": {
            "type": ["integer", "null"]
          },
          "engagement_rate": {
            "type": ["number", "null"]
          },
          "shares": {
            "type": ["integer", "null"]
          }
        }
      },
      "AccountAnalytics": {
        "type": "object",
        "properties": {
          "account_id": {
            "type": "string"
          },
          "object": {
            "const": "AccountAnalytics"
          },
          "provider": {
            "const": "X"
          },
          "from": {
            "type": "string"
          },
          "to": {
            "type": "string"
          },
          "read_at": {
            "type": "string",
            "format": "date-time"
          },
          "days": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AnalyticsDay"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/AnalyticsDay"
          },
          "followers": {
            "type": "object",
            "properties": {
              "total": {
                "type": "integer"
              },
              "verified": {
                "type": "integer"
              },
              "active": {
                "type": "integer"
              }
            }
          }
        }
      },
      "ArticleBlock": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "const": "text"
              },
              "html": {
                "type": "string",
                "maxLength": 100000
              },
              "plain": {
                "type": "string"
              }
            },
            "required": ["kind", "html"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "const": "image"
              },
              "alt": {
                "type": "string"
              },
              "file": {
                "$ref": "#/components/schemas/ArticleFile"
              }
            },
            "required": ["kind", "file"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "const": "code"
              },
              "text": {
                "type": "string",
                "maxLength": 100000
              }
            },
            "required": ["kind", "text"]
          }
        ]
      },
      "ArticleFile": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "content_type": {
            "type": "string",
            "enum": ["image/jpeg", "image/png", "image/webp"]
          },
          "data_base64": {
            "type": "string"
          }
        },
        "required": ["name", "content_type", "data_base64"]
      },
      "ArticleRequest": {
        "type": "object",
        "properties": {
          "account_id": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "cover": {
            "$ref": "#/components/schemas/ArticleFile"
          },
          "blocks": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "$ref": "#/components/schemas/ArticleBlock"
            },
            "description": "Images: 30 at most, 8 MB each, 40 MB in all."
          },
          "dry_run": {
            "type": "boolean",
            "description": "Builds and checks the draft but never publishes."
          }
        },
        "required": ["account_id", "title", "blocks"]
      },
      "ArticleJob": {
        "type": "object",
        "properties": {
          "object": {
            "const": "ArticleJob"
          },
          "id": {
            "type": "string"
          },
          "account_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["building", "published", "draft", "not_sent", "unknown"]
          },
          "url": {
            "type": "string"
          },
          "article_id": {
            "type": "string"
          },
          "draft_url": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          }
        }
      },
      "PageCaptureRequest": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "One of the addresses the capture opens, exactly."
          },
          "width": {
            "type": "integer",
            "minimum": 320,
            "maximum": 1280,
            "default": 520,
            "description": "CSS pixels (under 768, X and most sites draw their phone layout)."
          },
          "dpr": {
            "type": "integer",
            "minimum": 1,
            "maximum": 3,
            "default": 2
          },
          "clip": {
            "type": "object",
            "properties": {
              "maxHeight": {
                "type": "integer",
                "minimum": 100,
                "maximum": 4000,
                "default": 1600,
                "description": "CSS pixels: the picture stops there. `max_height` works too."
              },
              "selector": {
                "type": "string",
                "maxLength": 200,
                "description": "The picture is that element. Not on an X post."
              }
            }
          },
          "x_post": {
            "type": "object",
            "properties": {
              "counts": {
                "type": "boolean",
                "default": true,
                "description": "`false` leaves out the post's time and views row and its action bar (no views, replies, reposts, likes or bookmarks); the picture ends 16 px under its last content."
              }
            },
            "description": "X posts only: on another address it answers `400`."
          }
        },
        "required": ["url"]
      },
      "PageCapture": {
        "type": "object",
        "properties": {
          "object": {
            "const": "PageCapture"
          },
          "ok": {
            "type": "boolean"
          },
          "account_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "final_url": {
            "type": "string",
            "description": "`ok: true`: the address the page ended on."
          },
          "title": {
            "type": "string"
          },
          "width": {
            "type": "integer",
            "description": "Pixels of the JPEG: CSS width times `dpr`."
          },
          "height": {
            "type": "integer"
          },
          "jpeg_base64": {
            "type": "string",
            "description": "`ok: true`: the JPEG, base64, no `data:` prefix."
          },
          "captured_at": {
            "type": "string",
            "format": "date-time"
          },
          "code": {
            "type": "string",
            "enum": [
              "x_post_author_mismatch",
              "x_post_protected",
              "x_post_deleted",
              "x_post_age_restricted",
              "x_post_unavailable",
              "x_post_not_loaded",
              "x_signed_out",
              "x_app_not_loaded",
              "left_allowed_hosts",
              "url_not_allowed",
              "element_not_found",
              "browser_busy",
              "capture_blank",
              "counts_not_hidden",
              "no_picture",
              "capture_failed"
            ],
            "description": "`ok: false`: why there's no picture. `x_post_author_mismatch`: X shows the post under another handle than the address's, or no author it could read. `x_post_protected`: The post is from a protected account. `x_post_deleted`: X says the post doesn't exist: deleted, or never posted. `x_post_age_restricted`: X shows the post only behind an age or sensitive-content warning (never clicked through). `x_post_unavailable`: X shows its \"This post is unavailable\" notice. `x_post_not_loaded`: X ran but didn't show the post within 25 seconds. `x_signed_out`: X is signed out in the account's browser. `x_app_not_loaded`: X's app didn't load in the account's browser. `left_allowed_hosts`: The page went to another address after it loaded. `url_not_allowed`: The browser's own check refused the address. `element_not_found`: No element for `clip.selector` within 10 seconds. `browser_busy`: The account's browser was on another job: try again in a minute. `capture_blank`: The picture came out blank (almost all of it one colour), or X drew the post's box empty: it isn't returned. `counts_not_hidden`: Asked with `x_post: { counts: false }`, but the views row and action bar couldn't be hidden: no picture, never one with counts. `no_picture`: The browser gave no picture. `capture_failed`: The capture stopped."
          },
          "detail": {
            "type": "string",
            "description": "`ok: false`: the same, in words."
          }
        },
        "required": ["object", "ok", "account_id", "url", "captured_at"]
      },
      "WriteStatus": {
        "type": "object",
        "properties": {
          "object": {
            "const": "WriteStatus"
          },
          "key": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "enum": ["none", "pending", "done", "failed"]
          },
          "status": {
            "type": "integer"
          },
          "response": {
            "type": ["object", "null"]
          }
        }
      }
    }
  }
}
