Conversation
Invoice already has an `errors` field, but LineItem and Transaction did not. Add `errors = fields.Dict(allow_none=True)` to both schemas so validation errors returned by the API are accessible on nested objects. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `id` field to Account schema so the account identifier is accessible. Add `churn_recognition` and `churn_when_zero_mrr` fields to support the optional `include` query parameter on the /account endpoint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Invoice.update_status (PATCH /invoices/{uuid}) for updating invoice
status and Invoice.disable (PATCH /invoices/{uuid}/disable) for
disabling invoices.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SubscriptionEvent.destroy() and .modify() that accept flat params
(e.g. data={"id": 123}) and auto-wrap in the subscription_event
envelope. The old _with_params methods are preserved for backwards
compatibility.
Add SubscriptionEvent.disable() and .enable() convenience methods
for toggling the disabled state of subscription events.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add edge case, error path, and backwards-compatibility tests: Invoice: - Verify update_status request body is sent correctly - 404 error paths for update_status and disable - Verify disable sends no request body - LineItem/Transaction errors=None and errors-absent cases SubscriptionEvent: - Flat destroy/modify with external_id+data_source_uuid - Passthrough when caller already wraps in envelope (no double-wrap) - disable/enable with external_id+data_source_uuid identification Account: - Graceful handling when id field absent from response - Single include param Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the Python SDK to support additional API response fields and adds/adjusts client methods for invoice and subscription event operations, with accompanying test coverage.
Changes:
- Add deserialization support for
errorson invoice line items/transactions and for additional account fields (id, churn settings). - Add invoice endpoints for updating status and disabling invoices.
- Add
SubscriptionEvent.destroy/modify/disable/enablehelpers that accept “flat” params and wrap them in the requiredsubscription_eventenvelope, plus tests for these behaviors.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
chartmogul/api/transaction.py |
Adds errors field support on Transaction schema. |
chartmogul/api/invoice.py |
Adds errors support on invoice-related schemas and introduces update_status / disable methods. |
chartmogul/api/account.py |
Extends Account schema with optional id and churn-related fields. |
chartmogul/api/subscription_event.py |
Adds wrapper methods to accept flat params and to enable/disable subscription events. |
test/api/test_invoice.py |
Adds tests for nested errors fields and new invoice status/disable endpoints. |
test/api/test_account.py |
Adds tests for newly supported account fields and include query behavior. |
test/api/test_subscription_event.py |
Adds tests for flat-parameter wrapping and enable/disable helpers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
- Invoice.disable: rename method from "patch" to "disable" and add "disable" to _validate_arguments uuid check so calling without uuid raises ArgumentMissingError instead of silently producing a bad URL - SubscriptionEvent._disable/_enable: copy caller dict before mutation to avoid side effects; when payload is already wrapped in a subscription_event envelope, set the disabled flag inside it rather than at the top level Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d field, clean up tests - Move destroy/modify/disable/enable from module-scope into SubscriptionEvent as proper classmethods - Add disabled field to SubscriptionEvent schema so API responses are fully deserialized - Defensive dict() copy in destroy/modify for consistency with disable/enable - Rename camelCase test fixtures to snake_case, reduce duplication via spread and helper Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The API returns a boolean for churn_when_zero_mrr, not a string. Using fields.Raw allows any JSON type to be deserialized correctly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
loomchild
left a comment
There was a problem hiding this comment.
I don't really understand the changes. Maybe best ask someone who implemented the SDK before. I see it was changed a while ago, and many people aren't here anymore. @MariaBraganca - do you remember how the method is supposed to work by any chance?
| # This enforces user to pass argument, otherwise we could call | ||
| # wrong URL. | ||
| if method in ["destroy", "cancel", "retrieve", "modify", "update"] and "uuid" not in kwargs: | ||
| if method in ["destroy", "cancel", "retrieve", "modify", "update", "disable"] and "uuid" not in kwargs: |
There was a problem hiding this comment.
[question] Shouldn't it also include enable?
|
|
||
| @classmethod | ||
| def destroy(cls, config, **kwargs): | ||
| """Accept flat params and wrap in subscription_event envelope for the API.""" |
There was a problem hiding this comment.
[question] This seems a bit complicated. Is this pattern used anywhere else in the code?
| data["subscription_event"]["disabled"] = True | ||
| else: | ||
| data["disabled"] = True | ||
| data = {"subscription_event": data} |
| return cls.destroy_with_params(config, data=data) | ||
|
|
||
| @classmethod | ||
| def modify(cls, config, **kwargs): |
There was a problem hiding this comment.
[question] Why do you have to implement modify here, if it's already defined in resource? Can't you do something like SubscriptionEvent.modify = SubscriptionEvent._method(? There's also already .modify_with_params - isn't it sufficient?
| return cls.modify_with_params(config, data=data) | ||
|
|
||
| @classmethod | ||
| def disable(cls, config, **kwargs): |
There was a problem hiding this comment.
[question] Shouldn't this be defined in resource as well?
Summary
errorsfield onLineItemandTransactionschemas (Invoice already had it)id,churn_recognition,churn_when_zero_mrrfields toAccountschema; supportincludequery param on/accountInvoice.update_status(PATCH) andInvoice.disable(PATCH/invoices/{uuid}/disable)destroy()/modify()wrappers that accept flat params instead of requiringsubscription_event: {...}envelope; adddisable()/enable()convenience methodsBackwards compatibility review
All changes are purely additive — no existing public API surface was modified or removed.
account.pyid,churn_recognition,churn_when_zero_mrrschema fields (allow_none=True)invoice.pyerrorsfield toLineItem._Schema(allow_none=True)invoice.pyInvoice.update_statusandInvoice.disablemethodstransaction.pyerrorsfield toTransaction._Schema(allow_none=True)subscription_event.pydisabledfield to schema (allow_none=True)subscription_event.pydestroy,modify,disable,enableclassmethodsdestroy_with_params/modify_with_paramsunchangedresource.py"disable"to uuid-required validation listInvoice.disablemethod; no existing method used this nameTest plan
Testing instructions
Integration tests were run against account WiktorOnboarding (
acc_d0ea225e-f0f1-40ab-92cf-659dce5f2b76). To obtain the API key, impersonatewiktor@chartmogul.comin the admin panel and find it under Profile > API keys. The full test script is atsdks/tests/py/test_pip_310.py— set theCHARTMOGUL_API_KEYenv var and run it.Account.id field (PIP-120)
Account include query param (PIP-76)
LineItem and Transaction errors field (PIP-304)
Invoice.retrieve with query params
Invoice.update_status
Invoice.disable
Invoice.all with query params
SubscriptionEvent.disabled schema field
SubscriptionEvent.modify — flat params and envelope passthrough
SubscriptionEvent.destroy — flat params and envelope passthrough
SubscriptionEvent.disable and enable
🤖 Generated with Claude Code