Changelog¶
All notable changes to pypresscart are recorded here. This project follows Semantic Versioning.
Unreleased¶
0.1.8 — 2026-06-12¶
Added¶
CheckoutRequest.apply_credits(bool | None) — new optional body field onPOST /orders/checkout. Omit it (the defaultNone, dropped from the payload) to let the API apply available Team Credits, or passFalseto skip credits and pay in full.
0.1.7 — 2026-05-30¶
Added¶
client.articles.list_comments(),create_comment(),update_comment(), andarchive_comment()— full coverage of the article Comments API (GET/POST/PUT/DELETE /articles/{article_id}/comments[/{comment_reference}]). Comments support one level of replies viaparent_comment_id; the short reference returned asid(not a UUID) is the handle for update/archive. New models:Comment,CommentList,CommentAuthor,CommentAuthorInput,CommentCreateRequest,CommentUpdateRequest, andCommentArchiveResponse(empty — the archive endpoint responds204 No Content). All dual-mode. The comment endpoints use thearticles.read/articles.lists/articles.create/articles.update/articles.deletescopes.
0.1.6 — 2026-05-14¶
Fixed¶
client.campaigns.create()now sends the nullable body fields (description,keywords,target_audience,tone,writing_samples,file_id) as explicitnulls instead of dropping them.POST /campaignsrequires these keys to be present in the payload even when null;_serializepreviously usedexclude_none=Trueunconditionally, so aCampaignCreateRequestbuilt with the nullable fields left at theirNonedefaults produced a payload the API rejected._serializenow takes anexclude_nonekeyword (defaultTrue, unchanged for every other endpoint);campaigns.createopts intoexclude_none=False. Plaindictbodies are still passed through untouched.
0.1.5 — 2026-05-10¶
Added¶
client.orders.get(order_id, include_outlets_data=True)— new keyword-only parameter that requests a fully-populatedoutletblock (id,name,logo,website_url) on each line item instead of the lean shape. Defaults toNone, in which case the parameter is omitted from the URL and existing call sites are byte-for-byte unchanged on the wire.
0.1.4 — 2026-05-08¶
Added¶
Order.nameandOrder.email— top-level fields returned byGET /orders/{order_id}(the list endpoint nests these asteam.name/team.contact_email; both shapes are now modelled in parallel).LineItem.includes: list[IncludeItem] | None— channel/placement array surfaced onGET /orders/{order_id}line items.
Fixed¶
LineItem.idandLineItem.order_idare now optional. The Presscart API doesn’t populate them on the leanPOST /orders/checkoutresponse (line items are only persisted with an id once the order is paid, exposed viaGET /order-items), which previously caused checkout responses to fail Pydantic validation.
Changed¶
Removed the strict-
xfailtrip-wire on thetests/integration/test_articles.py::test_get_articlelive test. Presscart fixed theGET /articles/{article_id}403 forfull_accessAPI tokens (issue #8), and the live test now passes. Documentation underdocs/testing-status.mdanddocs/resource-articles.mdupdated accordingly.
0.1.3 — 2026-04-18¶
Fixed¶
OutletChannel.do_follow_links_allowednow accepts string values (e.g."Unlimited") in addition tobool/null. The Presscart API returns a capacity string here on some outlet channels even though the docs type it as a boolean, which was causingGET /outlets/{id}to raise a PydanticValidationErrorwhenever one of those channels appeared in the response.
0.1.2 — 2026-04-18¶
Fixed¶
serialize_filtersnow emits list-valued filters in the indexed-bracket form (filters[key][0]=v1&filters[key][1]=v2) that the Presscart API actually parses. The previous bare-bracket form (filters[key][]=v1) was silently ignored by the server, causing any query usingdisclaimer_ids,placement_types,channel_types,tags, orproduct_idsto return the full unfiltered result set instead of the expected subset.
0.1.1 — 2026-04-18¶
Housekeeping release. No runtime behavior changes.
Changed¶
Project URLs in
pyproject.toml(and therefore the Project links sidebar on PyPI) now point at the new ownerpypresscart/py-presscart. 0.1.0 still shipped with the originalannjawn/py-presscartURLs baked into its metadata; GitHub redirects preserve them, but 0.1.1 is the first release published under the canonical URLs.Docs site moved from
www.anjanbiswas.dev/py-presscart/to https://pypresscart.github.io/py-presscart/ as a side-effect of the repo transfer to the newpypresscartGitHub org.README now documents the full release procedure end-to-end and notes that
mainis protected (CI must pass, no direct pushes, force-pushes and deletions denied).
0.1.0 — Initial release¶
Initial public release.
Added¶
PresscartClientwith composable resource services:auth,outlets,products,orders,order_items,profiles,campaigns,articles,files,folders.Full coverage of the Presscart API as of release date (40+ endpoints).
Pydantic models for every request and response shape.
Dual-mode I/O: accept and return either Pydantic models or
dicts, controllable per-call (as_json=) or at the client level (response_mode=).Typed exception hierarchy with
BadRequestError,ValidationError,AuthenticationError,PermissionError,NotFoundError,RateLimitError,ServerError, andPresscartTransportError.Automatic exponential-backoff retry on 429/5xx/network errors, honoring
Retry-After.Context-manager lifecycle.
Typed throughout (
py.typedshipped; mypy-strict clean).
Dependencies¶
Runtime:
pydantic>=2.7,<3,requests>=2.31,<3.Python 3.10+.