Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@

All notable changes to `fopost` are documented here.

## 0.4.0 - 2026-10-18

### Added

- `client.queue`: `list_slots`, `create_slot`, `update_slot`, `delete_slot`, `next` and
`preview` for the posting queue, and `schedule="queue"` on `posts.create` and `posts.update`
to take the next free slot instead of a `schedule_at`.
- `client.connect_sessions`: `create` and `get` for hosted connect links (`ConnectSession`).
- `client.webhook_endpoints`: `list`, `create`, `update`, `delete`, `test`, `deliveries`,
`get_delivery` and `redeliver` (`WebhookEndpoint`, `WebhookDelivery`, `WEBHOOK_EVENTS`). The
name is deliberately not `webhooks`, which stays the signature-verification module.
- `client.automations`: `list`, `create`, `get`, `update`, `delete`, `toggle`, `stats`,
`versions`, `get_version`, `restore_version`, `runs` and `get_run` (`Automation`,
`AutomationVersion`, `AutomationRun`, `AutomationStats`, `AUTOMATION_TRIGGER_TYPES`).
- `client.logs.list` for the request log, with `meta.next_cursor` and `summary`
(`RequestLogPage`).
- `posts.unpublish` (`UnpublishResult`) and bulk import: `posts.validate_bulk_import`,
`posts.commit_bulk_import`, `posts.rollback_bulk_import`.
- `workspaces.create`, `workspaces.update`, `workspaces.delete`; `labels.create`, `labels.get`,
`labels.update`, `labels.delete`.
- `accounts.toggle_primary`, `accounts.validate_credentials` and `accounts.refresh_token`
(`AccountPrimary`, `AccountValidation`, `AccountTokenRefresh`).
- `accounts.list_communities`, `sync_communities`, `search_communities`, `add_community` and
`remove_community` for X communities (`Community`, `CommunitySearchResult`).
- `media.list`, `media.upload` (multipart, up to 5 files) and `media.delete`; `MediaItem` carries
the library-row fields (`workspace_id`, `mime_type`, `tags`, `folder_id`, `brand_role`, …).
- `analytics.overview`, `time_series`, `top_posts`, `labels`, `posts_table`, `posting_streak`,
`demographics`, `inbox` and `collect`, typed as `AnalyticsOverview`, `AnalyticsTimeSeries`,
`TopPost`, `LabelAnalytics`, `PostsTable`, `PostingStreakDay`, `AudienceDemographics`,
`InboxAnalytics` and `AnalyticsCollectResult`.
- `Workspace.connect_redirect_domains` and `updated_at`; `Label.created_at` and `updated_at`.

## 0.3.0 - 2026-10-18

### Removed
Expand Down
29 changes: 19 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Guidance for Claude Code (claude.ai/code) when working in this repository.
## What This Is

`fopost` on PyPI — the official Python client for the FoPost REST API (`fopost.com`).
Current version `0.3.0`. It wraps the API's HTTP surface in a namespaced client
(`posts`, `accounts`, `account_groups`, `workspaces`, `labels`, `ai`, `inbox`, `contacts`, `broadcasts`, `sequences`, `ads`) returning pydantic v2 models.
Current version `0.4.0`. It wraps the API's HTTP surface in a namespaced client
(`posts`, `accounts`, `account_groups`, `workspaces`, `labels`, `media`, `ai`, `inbox`, `contacts`, `broadcasts`, `sequences`, `ads`, `queue`, `connect_sessions`, `webhook_endpoints`, `automations`, `logs`, …) returning pydantic v2 models.

Requires Python >= 3.10 (CI matrix: 3.10–3.13). Runtime deps: `httpx>=0.27`,
`pydantic>=2.7`. Built with hatchling from `src/fopost`, ships `py.typed`.
Expand Down Expand Up @@ -48,7 +48,8 @@ src/fopost/
chat_adapter.py ChatAdapter — the inbox as a send/receive interface, imported on its own
resources/ _base.py (Resource, parse_list, UNSET, drop_unset)
posts.py accounts.py account_groups.py workspaces.py labels.py ai.py
inbox.py contacts.py broadcasts.py ads.py
inbox.py contacts.py broadcasts.py ads.py media.py analytics.py
queue.py connect_sessions.py webhook_endpoints.py automations.py logs.py
```

Request flow: a resource method builds a snake_case body/params dict, calls
Expand Down Expand Up @@ -110,13 +111,21 @@ TypeScript SDK.
- Escape hatch: `client.request(method, path, json=..., params=...)` returns the decoded
body with no unwrap and no model parsing.

Resource coverage is a subset of the API: posts (list/iter/iter_pages/get/create/update/
delete/publish/cancel/retry/preflight/deliveries), accounts (list/get/health/update/move, Telegram connect code and bot commands, Slack channels, members and posting identity),
account_groups (list/create/get/update/delete/set_members), workspaces
(list/get), labels (list), ai (credits/generate_caption/rewrite/repurpose_url), inbox (the `/v1/inbox`
family except the X Chat routes), ads (the `/v1/ads` family), validate (post/length/media). `communities`, `webhooks`,
`analytics`, `automations`, and `media` are **not wrapped here** — the Go and Rust SDKs have
them. Adding one is a public-surface change: see the Downstream Packages rule.
Resource coverage: posts (list/iter/iter_pages/get/create/update/delete/publish/cancel/retry/
preflight/unpublish/deliveries, bulk import validate/commit/rollback, `schedule="queue"` on
create and update), accounts (list/get/health/update/move, X communities, Telegram connect code
and bot commands, Slack channels, members and posting identity, …), account_groups
(list/create/get/update/delete/set_members), workspaces (list/get/create/update/delete), labels
(list/create/get/update/delete), media (list/upload/delete/limits/presign/complete/upload_direct),
ai (credits/generate_caption/rewrite/repurpose_url), inbox (the `/v1/inbox` family except the X
Chat routes), ads (the `/v1/ads` family), validate (post/length/media), analytics (dashboard
reads plus decay/frequency/timeline/changes), queue (slots CRUD, next, preview), connect_sessions
(create/get), webhook_endpoints (CRUD, test, deliveries, redeliver), automations (CRUD, toggle,
stats, versions, runs), logs (list). **`client.webhook_endpoints` manages outbound endpoints;
`fopost.webhooks` (the module) verifies the deliveries they receive** — the names differ on
purpose so `from fopost import webhooks` keeps meaning the verifier. The checker in
`fopost-api-collections` (`scripts/sdk-gaps.mjs`) must report no gap before a release. Adding a
resource is a public-surface change: see the Downstream Packages rule.

## Commands

Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,12 +312,12 @@ except FopostError as err:

| Namespace | Methods |
| ------------ | -------------------------------------------------------------------------------------- |
| `posts` | `list`, `iter`, `iter_pages`, `get`, `create`, `update`, `delete`, `publish`, `cancel`, `retry`, `preflight`, `deliveries` |
| `accounts` | `list`, `get`, `health`, `update`, `move`, `create_telegram_connect_code`, `get_telegram_connect_status`, `get_telegram_bot_commands`, `set_telegram_bot_commands`, `delete_telegram_bot_commands`, `list_slack_channels`, `list_slack_members`, `get_slack_identity`, `update_slack_identity`, `list_reddit_subreddits`, `list_reddit_subreddit_rules`, `list_reddit_flairs`, `set_reddit_default_subreddit`, `get_ice_breakers`, `set_ice_breakers`, `delete_ice_breakers`, `get_persistent_menu`, `set_persistent_menu`, `delete_persistent_menu`, `get_greeting`, `set_greeting`, `delete_greeting`, `get_webhook_subscription`, `resubscribe_webhook`, `list_discord_channels`, `switch_discord_channel`, `get_discord_identity`, `update_discord_identity`, `list_discord_pins`, `delete_discord_message`, `pin_discord_message`, `unpin_discord_message`, `crosspost_discord_message`, `create_discord_thread`, `send_discord_dm`, `list_discord_events`, `get_discord_event`, `create_discord_event`, `update_discord_event`, `delete_discord_event`, `list_discord_members`, `get_discord_member`, `list_discord_roles`, `create_discord_role`, `update_discord_role`, `delete_discord_role`, `add_discord_member_role`, `remove_discord_member_role`, `platform_metrics` |
| `posts` | `list`, `iter`, `iter_pages`, `get`, `create`, `update`, `delete`, `publish`, `cancel`, `retry`, `preflight`, `unpublish`, `deliveries`, `validate_bulk_import`, `commit_bulk_import`, `rollback_bulk_import` |
| `accounts` | `list`, `get`, `health`, `update`, `move`, `toggle_primary`, `validate_credentials`, `refresh_token`, `create_telegram_connect_code`, `get_telegram_connect_status`, `get_telegram_bot_commands`, `set_telegram_bot_commands`, `delete_telegram_bot_commands`, `list_slack_channels`, `list_slack_members`, `get_slack_identity`, `update_slack_identity`, `list_communities`, `sync_communities`, `search_communities`, `add_community`, `remove_community`, `list_reddit_subreddits`, `list_reddit_subreddit_rules`, `list_reddit_flairs`, `set_reddit_default_subreddit`, `get_ice_breakers`, `set_ice_breakers`, `delete_ice_breakers`, `get_persistent_menu`, `set_persistent_menu`, `delete_persistent_menu`, `get_greeting`, `set_greeting`, `delete_greeting`, `get_webhook_subscription`, `resubscribe_webhook`, `list_discord_channels`, `switch_discord_channel`, `get_discord_identity`, `update_discord_identity`, `list_discord_pins`, `delete_discord_message`, `pin_discord_message`, `unpin_discord_message`, `crosspost_discord_message`, `create_discord_thread`, `send_discord_dm`, `list_discord_events`, `get_discord_event`, `create_discord_event`, `update_discord_event`, `delete_discord_event`, `list_discord_members`, `get_discord_member`, `list_discord_roles`, `create_discord_role`, `update_discord_role`, `delete_discord_role`, `add_discord_member_role`, `remove_discord_member_role`, `platform_metrics` |
| `account_groups` | `list`, `create`, `get`, `update`, `delete`, `set_members` |
| `workspaces` | `list`, `get` |
| `labels` | `list` |
| `media` | `limits`, `presign`, `complete`, `upload_direct` |
| `workspaces` | `list`, `get`, `create`, `update`, `delete` |
| `labels` | `list`, `create`, `get`, `update`, `delete` |
| `media` | `list`, `upload`, `delete`, `limits`, `presign`, `complete`, `upload_direct` |
| `ai` | `credits`, `generate_caption`, `rewrite`, `repurpose_url` |
| `inbox` | `list`, `threads`, `conversations`, `unread_count`, `accounts`, `platforms`, `mark_thread_read`, `refresh`, `update`, `edit_comment`, `reply`, `hide`, `unhide`, `delete`, `like`, `unlike`, `vote`, `pin`, `unpin`, `react`, `start_conversation`, `set_typing`, `handover`, `list_approvals`, `approve_reply`, `reject_reply` |
| `inbox` | `list`, `threads`, `conversations`, `unread_count`, `accounts`, `platforms`, `mark_thread_read`, `refresh`, `update`, `edit_comment`, `reply`, `hide`, `unhide`, `delete`, `like`, `unlike`, `vote`, `pin`, `unpin`, `react`, `start_conversation`, `set_typing`, `list_approvals`, `approve_reply`, `reject_reply` |
Expand All @@ -332,8 +332,13 @@ except FopostError as err:
| `blogs` | `list_blogs`, `list_articles`, `get_article`, `create_article`, `update_article`, `delete_article`, `list_products`, `update_product` |
| `validate` | `post`, `length`, `media`, `subreddit` |
| `whatsapp` | `get_profile`, `update_profile`, `request_display_name`, `set_username`, `list_templates`, `list_template_library`, `get_template`, `create_template`, `import_template`, `update_template`, `delete_template`, `list_groups`, `create_group`, `get_group`, `update_group`, `delete_group`, `get_group_invite_link`, `reset_group_invite_link`, `remove_group_participants`, `list_blocked`, `block_users`, `unblock_users`, `get_commerce_settings`, `update_commerce_settings`, `link_catalog`, `list_flows`, `get_flow`, `create_flow`, `update_flow`, `delete_flow`, `upload_flow_json`, `publish_flow`, `deprecate_flow`, `list_flow_responses`, `get_encryption_key_status`, `set_encryption_key`, `get_account_events`, `list_sandbox_sessions`, `create_sandbox_session` |
| `analytics` | `decay`, `frequency`, `timeline`, `changes`, `collect_post`, `native_posts` |
| `analytics` | `overview`, `time_series`, `top_posts`, `labels`, `posts_table`, `posting_streak`, `demographics`, `inbox`, `collect`, `decay`, `frequency`, `timeline`, `changes`, `collect_post`, `native_posts` |
| `activity` | `list` |
| `queue` | `list_slots`, `create_slot`, `update_slot`, `delete_slot`, `next`, `preview` |
| `connect_sessions` | `create`, `get` |
| `webhook_endpoints` | `list`, `create`, `update`, `delete`, `test`, `deliveries`, `get_delivery`, `redeliver` |
| `automations` | `list`, `create`, `get`, `update`, `delete`, `toggle`, `stats`, `versions`, `get_version`, `restore_version`, `runs`, `get_run` |
| `logs` | `list` |

For an endpoint the SDK does not wrap yet, `client.request` sends an
authenticated call and hands back the decoded body:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "fopost"
version = "0.3.0"
version = "0.4.0"
description = "Official Python SDK for the FoPost API. Schedule and publish to +30 social platforms from your code."
readme = "README.md"
license = "MIT"
Expand Down
Loading
Loading