All notable changes to the Late Python SDK will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- MCP
accounts_get_follower_statsreturned only the account name, dropping the follower count and daily series. The shared_format_responsehelper pattern-matches on the response shape, andFollowerStatsResponsehas anaccountsattribute, so it fell into the generic account-list branch that prints only- {platform}: {username}and silently discardedcurrentFollowers,growth, and the dailystatsseries. Hit in practice by a developer pulling LinkedIn org follower stats (data was present server-side: latest count plus a week of daily snapshots), who saw only the account name come back through the tool._format_responsenow checks for astatsattribute (unique toFollowerStatsResponseamong all response models) BEFORE the genericaccountsbranch and returns the fullmodel_dump_json(by_alias=True, exclude_none=True), so the count, growth, and series reach the LLM losslessly. Fixed in both the emittedgenerated_tools.pyand thegenerate_mcp_tools.pytemplate so a future regen keeps it. Two regression tests added intests/test_integration.py. (The related model gap,FollowerStatsResponsemissingstats/granularity, was already corrected ondevelopby an earlier OpenAPI regen, so no model change was needed here.)
- 1.4.48 was a regression: PATCH methods broke again. The auto-regen workflow runs on
develop, but the_patch/_apatchfix from 1.4.47 only landed onmain. Whendevelop's next regen built 1.4.48 (against an updated OpenAPI spec that addedrequestBodyblocks forupdateSequence/updateBroadcast), it picked updevelop's oldbase.pywithout_patch, so any 1.4.48 customer who upgraded gotAttributeErroron every PATCH call again. 1.4.49 mergesdevelopintomain(keepingmain's_patch/_apatch) so the published wheel carries both fixes: the missing PATCH method and the new body kwargs onupdate_sequence(...)/update_broadcast(...). Skip 1.4.48 — upgrade straight from 1.4.47 to 1.4.49.
- Every PATCH endpoint was broken end-to-end.
BaseClientexposed_get,_post,_put,_deletebut never defined_patch(or its async counterpart_apatch), while the resource generator happily emittedself._client._patch(...)calls. Any call into a PATCH endpoint raisedAttributeError: 'Zernio' object has no attribute '_patch'before a request was sent. Hit in practice oncontacts.update_contact(caught when a customer tried to add a tag from the MCP), but the same bug took downupdate_comment_automation,update_custom_field,update_lead_form,update_whats_app_template,update_whats_app_flow,update_discord_settings,update_google_business_place_action,edit_inbox_message,configure_tik_tok_ads_brand_identity,complete_telegram_connect,update_sequence, andupdate_broadcast(sync + async = 26 methods total).BaseClientnow defines_patch/_apatchmirroring_put/_aput, with aparams=kwarg so the one query-only PATCH (complete_telegram_connect) keeps working. Regression test intests/test_patch_methods.pyexercises body-bearing and query-only PATCH through the resource layer against a mocked HTTP client, so future codegen drifts can't silently reintroduce this. (Originally targeted 1.4.6 onmain; that tag had already been taken by an auto-regen ondevelop, so this fix ships as 1.4.47 after mergingdevelopintomain.)
- Optional scalar params no longer ship zero values to the API. The MCP autogenerator was emitting
0/0.0/""/Falseas defaults for optional scalars without OpenAPI-declared defaults, which the SDK's_build_payloadcouldn't filter (it only dropsNone). The literal0.0then tripped Zod'sz.number().positive().optional()validators server-side, surfacing as[400] Number must be greater than 0even when the field was genuinely optional. Hit in practice onads_create_standalone_adfor Google Search campaigns whereroas_average_floordefaulted to0.0and was forwarded into the API. Optional scalars now default toNone(typed asT | None) so unset fields are dropped before reaching the server. OpenAPI-declared defaults (e.g.campaign_type="display",gender="all") are still respected. LateAPIErrornow surfaces field names and stable error codes. The API returns{error, type, code, param}on validation failures but the SDK was readingerror_data.get("details")(a key the API doesn't send), soparamwas always lost. The SDK now stores the full envelope indetails, and__str__formats as[400] {message} (field: {param}; code: {code})when those are present. Direct fix for Hein's "the error doesn't identify the offending field" feedback.
- Merged the multi-account routing fix (1.4.0, originally landed on
main) and the array/object schema fix (1.4.1, alsomain) into thedevelopbranch so the next OpenAPI auto-regen doesn't reintroduce the bugs. Develop now has both fixes applied on top of its accumulated auto-regen content (new endpoints up through v1.3.120). No new behavioural changes beyond 1.4.1. - Generator now combines
develop's param/tool-name dedupe (prevents duplicate-kwarg SyntaxErrors and F811 lint failures) withmain's$ref/allOfschema resolution andlist[T]/dict[str, Any]typing. With develop's newer OpenAPI spec, this means newer fields onads_create_standalone_ad(cities,regions,creatives,images,video,brand_identity,promoted_object) are now properly typed alongside the original four (keywords,countries,additional_headlines,additional_descriptions).
- Autogenerated MCP tools no longer collapse
arrayandobjectschemas tostr. Fields likekeywords,countries,additional_headlines,additional_descriptionsonads_create_standalone_ad(and the equivalents across every autogenerated tool) were declared asstrand forwarded straight into the SDK, which then rejected the request withExpected array, received string. They now use the correct Python types (list[str] | None,list[dict[str, Any]] | None,dict[str, Any] | None) so FastMCP advertises the right shape to LLMs and the SDK receives native containers. - The generator now dereferences
$ref,allOf, and same-typeoneOf/anyOfwrappers when reading a schema's type. Without this, properties likeposts_create_post.tiktokSettings,posts_create_post.facebookSettings,posts_create_post.recycling, and array-of-$ref fields likecreateWhatsAppTemplate.components,createQueueSlot.slots,sendConversions.events,updateGoogleBusinessFoodMenus.menus, andsendPrivateReplyToComment.buttonswould still have leaked through asstr.
- MCP multi-account routing (silent-wrong-account bug).
posts_create,posts_publish_now,posts_cross_post, andaccounts_getpreviously fell back to the first matching account (matching[0]) when the user had more than one account on the requested platform. Agency / multi-client setups could see posts land on the wrong account with no warning. These tools now return an explicit error listing the candidate account IDs when the selection is ambiguous, and require the caller to disambiguate.
account_idandprofile_idparameters onposts_createandposts_publish_nowfor explicit target selection.account_ids(parallel toplatforms) andprofile_idparameters onposts_cross_post. Repeating a platform with different IDs is supported (e.g. cross-posting to two Twitter accounts in one call).posts_create_postexposed as an autogenerated tool alongside the simplifiedposts_create. It mirrors the full RESTcreatePostsurface (nestedplatformsarray withcustomContent,customMedia,scheduledFor,platformSpecificData) for power users who need per-target customisation.- Top-level multi-account workflow guidance in the MCP server instructions so LLMs learn the disambiguation flow once globally.
- Unit tests for the shared
_resolve_accounthelper covering account-id, profile-id, ambiguous, and not-found paths.
- MCP HTTP server now exposes the modern Streamable HTTP transport at
POST /mcp(in addition to the existing SSE transport atGET /sse). Streamable HTTP is recommended for new clients (Claude Code,mcp-remote, etc.) because it is not affected by the idle-connection drops that affect long-lived SSE connections behind proxies. - Streamable HTTP runs in stateless mode — each request is fully independent and authenticated separately via the
Authorization: Bearerheader.
- Bumped minimum
mcpSDK version to>=1.8.0(required forStreamableHTTPSessionManager). - Server
transportfield in the root info endpoint now reports"sse+streamable-http".
- MCP (Model Context Protocol) server support for Claude Desktop integration
- HTTP server mode for MCP (
late-mcp-http) - AI content generation module with OpenAI and Anthropic support
- Pipelines for common workflows (CSV scheduler, cross-poster)
- Large file upload support via Vercel Blob
- Progress callbacks for file uploads
- Comprehensive test suite with pytest
- Improved error handling with specialized exception classes
- Better async support throughout the SDK
- Upload module with
SmartUploaderfor automatic upload strategy selection - Direct upload for files under 4MB
- Multipart upload support for large files
upload_bytes()andupload_large_bytes()methods
- Initial public release
- Full coverage of Late API endpoints
- Support for all 13 social media platforms: Instagram, TikTok, YouTube, LinkedIn, X/Twitter, Facebook, Pinterest, Threads, Bluesky, Reddit, Snapchat, Telegram, and Google Business Profile
- Async support with
alist(),acreate(), etc. - Type hints and Pydantic models
- Error handling with
LateAPIError,LateRateLimitError,LateValidationError
- Posts: create, list, get, update, delete, retry, bulk upload
- Accounts: list, get, follower stats
- Profiles: create, list, get, update, delete
- Analytics: get metrics, usage stats
- Account Groups: create, list, update, delete
- Queue: slots management, preview
- Webhooks: settings management, logs, testing
- API Keys: create, list, delete
- Media: upload, generate upload token
- Tools: downloads, hashtag checking, transcripts, AI caption generation
- Users: list, get
- Usage: stats
- Logs: list, get
- Connect: OAuth flows for all platforms
- Reddit: feed, search
- Invites: platform invites management