nextmail.billing
Every method in this namespace: its signature, its parameters, what it returns and an example.
Methods
The plan of the workspace and what it costs, as Billing shows them: the plan and its usage, the plans on sale, pay as you go, every charge with its invoice, and the links that start a checkout or open the billing portal. Only the workspace owner reaches it, and nothing is paid through the API.
billing.get()billing.list_plans()billing.get_usage()billing.list_alerts()billing.list_countries()billing.get_pay_as_you_go()billing.set_pay_as_you_go()billing.set_pay_as_you_go_limit()billing.confirm_pay_as_you_go()billing.start_checkout()billing.open_portal()billing.list_invoices()billing.get_invoice()billing.save_invoice_details()billing.list_add_ons()billing.start_add_on_checkout()billing.cancel_add_on()
billing.get()
Read the plan
def get(*, api_key: str | None = None, timeout: float | None = None) -> BillingResourceReturns the plan of the workspace and what it includes, as Billing shows it: how it is billed, when it renews or ends and the next charge, how many domains it holds, how much of this month's sends and today's AI actions are used, and pay as you go. metered is False while billing is switched off, and then nothing is capped.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingResource with plan, interval, renewsAt, nextCharge, domains, usage and payAsYouGo.
Example
from nextmail import nextmail billing = nextmail.billing.get()sends = billing['usage']['sends']limit = 'no limit' if sends['limit'] is None else sends['limit'] print(billing['planName'], sends['used'], limit)Notes
A limit of
Nonemeans the plan has none.
Also available in
- API
GET /billing- TypeScript
nextmail.billing.get()- Ruby
billing.get- PHP
billing->get- Go
Billing.Get- Java
billing().get- C#
Billing.GetAsync- CLI
nextmail billing get
billing.list_plans()
List the plans
def list_plans( *, api_key: str | None = None, timeout: float | None = None,) -> BillingPlanListResourceReturns every plan, cheapest first, with its price in US cents and what it includes. available says whether it is on sale, and intervals the billing intervals it is sold at.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingPlanListResource, a dict with one BillingPlanResource per plan in data.
Example
from nextmail import nextmail plans = nextmail.billing.list_plans() for plan in plans['data']: if plan['available']: print(plan['name'], plan['monthlyPriceCents'] / 100, plan['intervals'])Also available in
billing.get_usage()
Read the usage history
def get_usage( *, days: BillingUsageWindow | None = None, api_key: str | None = None, timeout: float | None = None,) -> BillingUsageResourceReturns the sends and AI actions of each day, and what pay as you go extras cost each month, as the Usage charts show them.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
daysBillingUsageWindowHow many days back to go, an
intfrom 1 to 3,660, or'all'for every day since the workspace was made. The server defaults to 30.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingUsageResource with days, months, dailyAiActions and monthlySends.
Example
from nextmail import nextmail usage = nextmail.billing.get_usage(days=90) sent = sum(day['sends'] for day in usage['days']) print(sent, 'sends in the last 90 days')Also available in
billing.list_alerts()
List the billing alerts
def list_alerts( *, api_key: str | None = None, timeout: float | None = None,) -> BillingAlertListResourceReturns what the billing banner of the app would say now, most urgent first: a failed payment, paused pay as you go, sending or AI paused at a limit, a plan about to end, an allowance nearly used and a charge coming soon. An empty data list means there is nothing to say.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingAlertListResource, a dict with one BillingAlertResource per alert in data.
Example
from nextmail import nextmail alerts = nextmail.billing.list_alerts() for alert in alerts['data']: if alert['severity'] == 'blocked': print(alert['kind'], alert['target'], alert['at'])Notes
An alert keeps its
idwhile the same thing is true, so one that was dismissed can stay dismissed.
Also available in
billing.list_countries()
List the billing countries
def list_countries( *, api_key: str | None = None, timeout: float | None = None,) -> BillingCountryListResourceReturns every country a billing address can be in, as the two-letter ISO 3166 codes save_invoice_details takes as country.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingCountryListResource, a dict with the codes in data.
Example
from nextmail import nextmail countries = nextmail.billing.list_countries() print('DE' in countries['data'], len(countries['data']))Also available in
billing.get_pay_as_you_go()
Read pay as you go
def get_pay_as_you_go( *, api_key: str | None = None, timeout: float | None = None,) -> PayAsYouGoResourceReturns pay as you go on the workspace: whether usage past the allowances is billed, the monthly limit and what extras cost so far, the current billing period once it is set up, the limits that can be chosen and the prices.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
PayAsYouGoResource with the state, limits, prices and period.
Example
from nextmail import nextmail pay_as_you_go = nextmail.billing.get_pay_as_you_go() print(pay_as_you_go['enabled'], pay_as_you_go['spentCents'], pay_as_you_go['limitCents'])Notes
Amounts are in US cents.
Also available in
billing.set_pay_as_you_go()
Turn pay as you go on or off
def set_pay_as_you_go( body: PayAsYouGoSet, *, api_key: str | None = None, timeout: float | None = None,) -> PayAsYouGoSwitchResourceTurns pay as you go on or off, as the switch on Billing does. Off takes effect at once, and usage stops at the allowances. On takes effect at once when a card is already saved. The first time, checkoutUrl is a link where the person adds a card, and pay as you go starts once they have: call confirm_pay_as_you_go after they return.
Nothing is paid through the API: the person pays, changes the card or cancels on the billing provider's page the link opens, as they do from the app.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
body['enabled']boolRequiredTrueto turn it on,Falseto turn it off.body['theme']BillingTheme'light'or'dark', for the page the link opens.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
PayAsYouGoSwitchResource with enabled, suspended, activating and checkoutUrl.
Example
from nextmail import nextmail switch = nextmail.billing.set_pay_as_you_go({'enabled': True}) if switch['checkoutUrl']: print('Add a card here:', switch['checkoutUrl'])else: print('Pay as you go is on:', switch['enabled'])Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.Turning it on while pay as you go is unavailable is 503
billing_not_configured.The SDK does not retry it.
Also available in
billing.set_pay_as_you_go_limit()
Set the pay as you go limit
def set_pay_as_you_go_limit( body: PayAsYouGoLimitSet, *, api_key: str | None = None, timeout: float | None = None,) -> PayAsYouGoLimitResourceSets the monthly spending limit of pay as you go, in US cents, one of the amounts get_pay_as_you_go lists in limits. Extras stop for the rest of a calendar month once it is reached.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
body['limitCents']intRequiredThe limit in US cents: 1,000, 2,500, 5,000, 10,000, 25,000, 50,000, 100,000, 250,000 or 500,000, the values in
PAY_AS_YOU_GO_LIMITS_CENTS.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
PayAsYouGoLimitResource with limitCents.
Example
from nextmail import nextmail saved = nextmail.billing.set_pay_as_you_go_limit({'limitCents': 10_000}) print(saved['limitCents'] / 100, 'US dollars a month at most')Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.A workspace where pay as you go was never set up is 409
pay_as_you_go_not_enrolled.The SDK does not retry it.
Also available in
billing.confirm_pay_as_you_go()
Confirm pay as you go
def confirm_pay_as_you_go( *, api_key: str | None = None, timeout: float | None = None,) -> PayAsYouGoConfirmationResourceChecks with the billing provider whether the card from a pay as you go checkout was saved, and records it, as the app does when the person comes back from the checkout. enabled says whether pay as you go is on now.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
PayAsYouGoConfirmationResource with enabled.
Example
from nextmail import nextmail confirmation = nextmail.billing.confirm_pay_as_you_go() print('Pay as you go is on' if confirmation['enabled'] else 'No card was saved')Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.It is safe to call again.
The SDK does not retry it.
Also available in
billing.start_checkout()
Start a checkout
def start_checkout( body: BillingCheckoutCreate, *, api_key: str | None = None, timeout: float | None = None,) -> BillingCheckoutResourceStarts buying a paid plan for a workspace on Free, as choosing a plan in the app does, and returns the link to the checkout. Nothing is charged until the person pays there, and the plan starts once they have. A workspace that already pays for a plan changes it with open_portal instead.
Nothing is paid through the API: the person pays, changes the card or cancels on the billing provider's page the link opens, as they do from the app.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
body['plan']PaidPlanIdRequired'starter','business'or'enterprise'.body['interval']BillingInterval'month'or'year'. Defaults to'month'.body['theme']BillingTheme'light'or'dark', for the page the link opens.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingCheckoutResource with url.
Example
from nextmail import nextmail checkout = nextmail.billing.start_checkout({'plan': 'business', 'interval': 'year'}) print('Pay here:', checkout['url'])Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.A workspace that already pays for a plan is 409
plan_conflict, and a plan or interval that is not on sale is 422plan_unavailable.The SDK does not retry it.
Also available in
billing.open_portal()
Open the billing portal
def open_portal( body: BillingHandoff | None = None, *, api_key: str | None = None, timeout: float | None = None,) -> BillingPortalResourceReturns a link to the billing portal, where the person changes or cancels the plan, updates the card and downloads past invoices, as Manage does in the app. The body is optional.
Nothing is paid through the API: the person pays, changes the card or cancels on the billing provider's page the link opens, as they do from the app.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
body['theme']BillingTheme'light'or'dark', for the page the link opens.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingPortalResource with url.
Example
from nextmail import nextmail portal = nextmail.billing.open_portal({'theme': 'dark'}) print('Manage the plan here:', portal['url'])Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.The SDK does not retry it.
Also available in
billing.list_invoices()
List the charges
def list_invoices( *, page: int | None = None, limit: int | None = None, sort: BillingInvoiceSort | None = None, search: str | None = None, api_key: str | None = None, timeout: float | None = None,) -> BillingInvoiceListResourceReturns every charge of the workspace with the state of its invoice, a page at a time, as History on Billing lists them. Pages are numbered rather than cursored: ask for the next one with page= while hasMore is True. search= matches the plan, the invoice number, the charge id and the name billed.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
pageintWhich page, from 1.
limitintCharges per page, from 1 to 100. The server defaults to 25.
sortBillingInvoiceSort'newest', the default, or'oldest'.searchstrWords to look for, up to 120 characters.
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingInvoiceListResource, a dict with data, total, page, limit, hasMore and metered.
Example
from nextmail import nextmail charges = nextmail.billing.list_invoices(limit=10) for charge in charges['data']: if not charge['paid']: print(charge['id'], charge['amountCents'], charge['currency'], charge['status'])Notes
A provider that does not answer is 502
billing_unreachable.
Also available in
billing.get_invoice()
Get the invoice of a charge
def get_invoice( order_id: str, *, api_key: str | None = None, timeout: float | None = None,) -> BillingInvoiceLinkResourceReturns the link to the invoice of one charge, as a PDF, and its file name. An invoice that was not written yet is written first, which can take a few seconds. The link is signed by the billing provider, downloads the PDF and stops working after a while, so fetch it again rather than keeping it.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
order_idstrRequiredThe charge id, the
idof a charge inlist_invoices.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingInvoiceLinkResource with url and fileName.
Example
from nextmail import nextmail charges = nextmail.billing.list_invoices(limit=1) for charge in charges['data']: invoice = nextmail.billing.get_invoice(charge['id']) print(invoice['fileName'], invoice['url'])Notes
A charge with no billing name and address is 409
billing_details_required: save them withsave_invoice_details. A draft or void charge is 409invoice_unavailable, and an invoice still being written is 504invoice_not_ready.
Also available in
billing.save_invoice_details()
Save the billing details of a charge
def save_invoice_details( order_id: str, body: BillingDetailsSet, *, api_key: str | None = None, timeout: float | None = None,) -> BillingInvoiceDetailsResourceSaves the name and address billed on a charge, as the Billing address dialog does, keeps the address for later charges, and starts writing its invoice. invoice is 'ready' when the charge already had one, 'started' when it is being written, and 'refused' with the reason in message.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
order_idstrRequiredThe charge id, the
idof a charge inlist_invoices.body['name']strRequiredWho is billed, up to 200 characters.
body['line1']strRequiredThe street address, up to 200 characters.
body['line2']strA flat, suite or building, up to 200 characters.
body['city']strRequiredUp to 120 characters.
body['postalCode']strUp to 40 characters.
body['state']strThe state or region, up to 60 characters. In the US and Canada, its two-letter code.
body['country']strRequiredA two-letter ISO 3166 code, one of those
list_countriesreturns.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
BillingInvoiceDetailsResource with invoice and message.
Example
from nextmail import nextmail details = nextmail.billing.save_invoice_details( '3f6c2a9e-8b1d-4e7a-9c35-2d4f1b8e6a07', { 'name': 'Acme Ltd', 'line1': '1 Market Street', 'city': 'London', 'postalCode': 'EC1A 1AA', 'country': 'GB', },) print(details['invoice'], details['message'])Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.An address the billing provider refuses is 422
billing_address_rejected.The SDK does not retry it.
Also available in
billing.list_add_ons()
List add-ons
def list_add_ons( *, api_key: str | None = None, timeout: float | None = None,) -> AddOnListResourceReturns what can be bought on top of the plan, today the dedicated sending IP: whether it is for sale, its price per IP a month in priceCents, whether the workspace has it and when it ends, the IPs it brought, and eligibility, which says whether the workspace qualifies. A dedicated IP needs the Business or Enterprise plan and at least 100,000 emails sent in a month, because below that volume it delivers worse than the shared IPs.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
AddOnListResource, a dict with one AddOnResource per add-on in data: addOn, available, status, priceCents, endsAt, eligibility and ips.
Example
from nextmail import nextmail add_ons = nextmail.billing.list_add_ons() for add_on in add_ons['data']: print(add_on['addOn'], add_on['eligibility']['eligible'], add_on['eligibility']['reason'])Notes
statusisNoneuntil the workspace has the add-on.'pending'is paid and being set up,'warming'and'active'send through the dedicated IP, and'releasing'is being taken down.A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's
max_retries, and on a 429 only when it carries aRetry-Afterof a minute or less.
Also available in
billing.start_add_on_checkout()
Start a checkout for an add-on
def start_add_on_checkout( body: AddOnCheckoutCreate, *, api_key: str | None = None, timeout: float | None = None,) -> AddOnCheckoutResourceStarts buying an add-on, as the button under Billing does, and returns the link to the checkout. Nothing is charged until the person pays there. Once it is paid the dedicated IP is set up and warmed up, which sending.list_dedicated_ips shows.
Nothing is paid through the API: the person pays on the billing provider's page the link opens, as they do from the app.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
body['addOn']AddOnIdRequiredThe add-on to buy:
'dedicated-ip'.body['theme']BillingTheme'light'or'dark', for the page the link opens.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
AddOnCheckoutResource with addOn and url.
Example
from nextmail import nextmail checkout = nextmail.billing.start_add_on_checkout({'addOn': 'dedicated-ip'}) print('Pay here:', checkout['url'])Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.A workspace that already has the add-on is 409
add_on_already_active, one that does not qualify is 409add_on_not_eligible, and when every IP is taken it is 409add_on_sold_out. While add-ons are not on sale it is 503add_on_unavailable.The SDK does not retry it.
Also available in
billing.cancel_add_on()
Cancel an add-on
def cancel_add_on( add_on: AddOnId, *, api_key: str | None = None, timeout: float | None = None,) -> AddOnResourceCancels an add-on. It stays until the end of the month already paid for, which endsAt gives. Then the dedicated IP is released and mail leaves through the shared IPs again.
Billing belongs to the owner of the workspace: an API key acts for the owner, and an OAuth access token reaches billing only when the owner connected the app with every address. A token that acts for a member is 403 owner_only, and a key or token limited to particular addresses or domains is 422 capability_unsupported.
Parameters
add_onAddOnIdRequiredThe add-on to cancel:
'dedicated-ip'.api_keystrOverrides the client's API key for this call only.
timeoutfloatSeconds this call may take, the response included, before it raises
NextmailNetworkErrorwithis_timeout. It overrides the client'stimeoutfor this call, and0turns the limit off.
Returns
AddOnResource, now with endsAt set.
Example
from nextmail import nextmail add_on = nextmail.billing.cancel_add_on('dedicated-ip') print('Ends at', add_on['endsAt'])Notes
With an OAuth access token it asks for a verification code: until the app has verified one, it raises
NextmailApiErrorwith status 403, codestep_up_requiredandis_step_up_requiredset. An API key is never asked.A workspace that does not have the add-on, or whose add-on is already ending, is 409
add_on_not_active.The SDK does not retry a delete.
Google Workspace