Billing
https://d1y2lf8k3vrkfu.cloudfront.net/openapi/en-us/dest/AdvertisingBilling_prod_3p.json
Invoices, payments, the methods an account pays with, and the profiles that decide who gets charged.
- class ad_api.api.Billing(account: str = 'default', marketplace: Marketplaces = Marketplaces.EU, credentials: Dict[str, str] | None = None, proxies: Dict[str, str] | None = None, verify: bool = True, timeout: int | None = None, debug: bool = False, access_token: str | None = None, verify_additional_credentials: bool = True)
Note
The contract is
Advertising Billingversion 3.0 and carries no beta marker. Two invoice routes the contract lists,GET /invoicesandGET /invoices/{invoiceId}, live inad_api.api.Invoicesrather than here, where their subject belongs.### Endpoint map
:header-rows: 1 Path
Method
Kind
Answer
POST /billing/statuseslist_billing_statusread
200POST /billing/notificationslist_billing_notificationsread
200POST /invoiceSummaries/listinvoice_summariesread
200POST /billing/paymentMethods/listget_customer_payment_methodsread
200POST /billing/paymentAgreements/listget_payment_agreementsread
200GET /billing/documents/{documentId}get_billing_documentread
200GET /billingProfileAgreementContents/{id}get_billing_profile_agreement_contentread
200POST /billingProfiles/listlist_billing_profilesread
200POST /billingProfileUsages/listlist_billing_profile_usagesread
200GET /billingStatements/{requestId}get_billing_statementread
200POST /billing/invoices/paypay_invoiceswrite
200POST /billing/paymentAgreementscreate_payment_agreementswrite
200POST /billing/paymentProfilescreate_payment_profileswrite
207POST /billingProfilescreate_billing_profileswrite
207PUT /billingProfilesupdate_billing_profileswrite
207POST /billingProfileUsagesapply_billing_profilewrite
207POST /billingStatementscreate_billing_statementwrite
207Five of the writes answer
207, a multi-status: the answer reports per item rather than as a whole.### Two invoice routes, two date formats
Both read invoices, and they do not agree on much.
:header-rows: 1 Invoices.list_invoicesBilling.invoice_summariesDates as
"20260902""2026-09-02"Fields as
plain strings
{"code": ..., "value": ...}pairsPayload shape
{"status": "success", "payload": {...}}{"invoiceSummaries": [...]}Filtering
by the caller
on the service
Page control
countandcursormaxResultsandnextTokenReading
Invoicesneeds the extra layer: the invoices sit atpayload["payload"]["invoiceSummaries"], andpayload["invoiceSummaries"]isNonewithout complaint.### Marketplace accounts are turned away
The billing profile routes refuse regional seller accounts:
POST /billingProfiles/list 400 The API doesnot support marketplace accounts POST /billingProfileUsages/list 400 Bad request received: only Global, Manager and Sponsored Ads marketplace accounts are supportedThat comes from the service, not the package. A Global, Manager or Sponsored Ads account reaches them.
### The required parameters the contract calls optional
Three routes name a query parameter without marking it required, and then refuse the call when it is missing.
:header-rows: 1 Route
Parameter
Accepted values
get_customer_payment_methodscriteriaTypePAY_NOW,AUTO_PAYget_payment_agreementsagreementTypePAY_NOW,AUTO_PAYget_billing_documentdocTypethe kind of document
Each answers
400naming the member it wanted.### Sorting invoice summaries
invoice_summariesacceptssortwith anattributeand adirection. The contract typesattributeas a plain string with no list of values, and only two are accepted:invoiceIssuedDateinvoiceDueDate
Anything else answers
400 Invalid input because of error(s): [sort:attribute field is invalid]. Those two are the names the answer uses, not the ones the filters use:invoiceDate,issuedDate,dueDate,amountDueandstatusare all refused.### pay_invoices does not name invoices
Its body carries no invoice ids. It names
targetCountryCodesand settles the open balance there through a payment agreement::header-rows: 1 Field
Type
Meaning
idempotenceIdstring
Required, and the only required member. The same id twice counts as one request, so a retry after a timeout does not charge twice.
modestring
EXECUTEcharges.PREVIEWsimulates and moves nothing.paymentAgreementIdstring
The agreement to charge. Omit it and the latest agreement is used.
reasonLocalestring
Locale of the reason text, such as
es_ES.targetCountryCodesarray
The countries whose balance is collected.
The answer carries
successandfailure, both always present, so a200alone does not mean the money moved.### The writes that were not exercised
Five routes change how an account is charged, and none was called:
pay_invoices— noISSUEDinvoice existed to settle, andEXECUTEmoves moneycreate_payment_agreements— creates a real agreementcreate_payment_profiles— a profile decides where money is taken fromcreate_billing_profilesandupdate_billing_profiles— change who gets invoicedapply_billing_profile— relinks countries to a profilecreate_billing_statement— starts a job
Four of them also have entries the contract never describes:
billingProfiles,billingProfileUsagesandpaymentProfilesare named as lists, and what an entry holds is not written down. Read one back from the matching list route before building a body.### Example: the invoices of a period
from ad_api.api import Billing client = Billing(account='my_account', debug=False) res = client.invoice_summaries(body={ "invoiceIssuedDateRangeFilter": { "startDate": "2026-09-01", "endDate": "2026-10-31", }, "statusValueFilter": {"include": ["PAID_IN_FULL"]}, "sort": {"attribute": "invoiceIssuedDate", "direction": "DESC"}, "maxResults": 50, }) for row in res.payload["invoiceSummaries"]: print(row["id"], row["invoiceIssuedDate"], row["status"]["code"], row["amountDue"]["value"], row["amountDue"]["currencyCode"])
### Example: what the account pays with
from ad_api.api import Billing client = Billing(account='my_account', debug=False) # criteriaType is required even though the contract lists it as optional methods = client.get_customer_payment_methods(criteriaType="AUTO_PAY") for card in methods.payload["creditCardPaymentMethods"]: print(card["brand"], card["tail"], card["expiryDetails"]) agreements = client.get_payment_agreements(agreementType="AUTO_PAY") for agreement in agreements.payload["paymentAgreements"]: for method in agreement["paymentProfile"]["paymentMethods"]: print(method.get("priority"), method.get("type"), method.get("brand"))
### Example: a statement request
from ad_api.api import Billing client = Billing(account='my_account', debug=False) res = client.create_billing_statement(body={ "startDate": "2026-09-01", "endDate": "2026-09-30", "locale": "es_ES", "countryCodes": ["ES"], "format": "CSV", }) # answers 207 and a request id request_id = res.payload.get("requestId") print(client.get_billing_statement(request_id).payload)
- list_billing_status(**kwargs) ApiResponse
Get the billing status for a list of advertising accounts.
- Request Body
- Bulk Get Billing Statuses Request Body {The properties needed to get the billing statuses for a set of advertisers.advertiserMarketplaces* (array) minItems: 0 maxItems: 100 [advertiserMarketplace {marketplaceId* (string)advertiserId* (string)}]locale (string) Locale. Enum: [‘ar_AE’, ‘cs_CZ’, ‘de_DE’, ‘en_AU’, ‘en_CA’, ‘en_GB’, ‘en_IN’, ‘en_SG’, ‘es_ES’, ‘es_MX’, ‘fr_CA’, ‘fr_FR’, ‘he_IL’, ‘hi_IN’, ‘it_IT’, ‘ja_JP’, ‘ko_KR’, ‘nl_NL’, ‘pl_PL’, ‘pt_BR’, ‘sv_SE’, ‘ta_IN’, ‘tr_TR’, ‘zh_CN’, ‘zh_TW’]}
- Returns
ApiResponse
- list_billing_notifications(**kwargs) ApiResponse
Get the billing notifications for a list advertising accounts.
- Request Body
- Bulk Get Billing Notifications Request Body {The properties needed to get the billing notifications for a set of advertisers.advertiserMarketplaces* (array) minItems: 0 maxItems: 100 [advertiserMarketplace {marketplaceId* (string)advertiserId* (string)}]locale (string) Locale. Enum: [‘ar_AE’, ‘cs_CZ’, ‘de_DE’, ‘en_AU’, ‘en_CA’, ‘en_GB’, ‘en_IN’, ‘en_SG’, ‘es_ES’, ‘es_MX’, ‘fr_CA’, ‘fr_FR’, ‘he_IL’, ‘hi_IN’, ‘it_IT’, ‘ja_JP’, ‘ko_KR’, ‘nl_NL’, ‘pl_PL’, ‘pt_BR’, ‘sv_SE’, ‘ta_IN’, ‘tr_TR’, ‘zh_CN’, ‘zh_TW’]}
- Returns
ApiResponse
- get_customer_payment_methods(**kwargs) ApiResponse
Lists the ways this account can pay.
Query
criteriaType(string): required.PAY_NOWorAUTO_PAY. The service answers400 Value null at 'criteriaType' failed to satisfy constraintwhen it is missing. It does not go in the body; this route takes no body.
- Returns
ApiResponse carrying five lists, always the same five, some empty:
creditCardPaymentMethodsexternalDeductFromPaymentPaymentMethodsexternalPayByInvoicePaymentMethodspayByInvoicePaymentMethodssellerPayablePaymentMethods
A card entry carries
brand,tail(the last four digits),expiryDetailswithmonthandyear,eligibleCountriesand aninstrumentIdthat identifies the instrument for later calls. Treat theinstrumentIdas a credential.
- pay_invoices(**kwargs) ApiResponse
Collects the outstanding balance for one or more countries.
This does not name invoices. The body carries no invoice ids: it names the countries whose debt is collected, and the service settles whatever is open there through a payment agreement. To read which invoices exist, use
Invoices.list_invoices.Warning
Written from the contract. No live call was possible: the account held no ISSUED invoice, and
EXECUTEmoves money.Request Body (required)
idempotenceId(string): required, and the only required member. Two requests carrying the same id are treated as one, so a retry after a timeout does not charge twice.mode(string):EXECUTEcharges,PREVIEWsimulates and moves nothing. UsePREVIEWto check a body before committing to it.paymentAgreementId(string): the agreement to charge, whose payment profile decides the method. Omit it and the advertiser’s latest agreement is used.reasonLocale(string): the locale of the reason text, such ases_ES.targetCountryCodes(array): the countries whose balance is collected. This is what selects the debt.
- Returns
ApiResponse carrying
successandfailure, both always present. An emptyfailuremeans every collection went through. A200does not by itself mean the money moved: readfailure.
- get_payment_agreements(**kwargs) ApiResponse
Lists the payment agreements this account holds.
Query
agreementType(string): required.AUTO_PAYorPAY_NOW. The service answers400 Value null at 'agreementType' failed to satisfy constraintwhen it is missing. It does not go in the body; this route takes no body.
- Returns
ApiResponse with
paymentAgreements, a list. An account that pays automatically holdsAUTO_PAYagreements and answers an empty list forPAY_NOW, and the reverse, so an empty answer here means the account holds none of that type rather than that the call failed.Each agreement carries a
paymentAgreementIdand apaymentProfilewhosepaymentMethodsare ordered bypriority, starting at 0. The lowest priority is tried first and the next covers if it cannot be charged.
- create_payment_agreements(**kwargs) ApiResponse
Creates a payment agreement, which decides how an account gets charged.
Warning
Written from the contract, and the contract describes this route thinly: it names the media type and nothing else. No body is documented here because none is documented there, and the call was not made because a payment agreement is not something to create by way of a test.
What the route takes can be inferred from
get_payment_agreements, which returns the shape it produces: an agreement carries apaymentProfilewhosepaymentMethodsare ordered bypriority. Building one means naming those methods.Read the live schema before using this. Until then, treat the body as unknown rather than copying a guess from here.
- Returns
ApiResponse with the created agreement, in the shape
get_payment_agreementslists.
- invoice_summaries(**kwargs) ApiResponse
Lists invoice summaries with filters, sorting and paging.
This is the route to reach for when the question is “which invoices fall in this period”.
Invoices.list_invoicesreturns a flat page and leaves the filtering to the caller; this one filters on the service, by issued date, due date, status, country, invoice number and payment method.Note the date format. Here it is ISO-8601 with the date alone,
"2026-09-01".Invoices.list_invoicesanswers dates as"20260902". The two shapes are not interchangeable.Request Body (optional)
Every member is optional. An empty object returns the first page.
invoiceIssuedDateRangeFilter(object):startDateandendDate, both inclusive, both"YYYY-MM-DD".invoiceDueDateRangeFilter(object): same shape, for the due date.statusValueFilter(object):include, a list of statuses such asPAID_IN_FULLorACCUMULATING.countryValueFilter(object):include, up to 30 country codes.invoiceNumberFilter(object):include, up to 30 invoice numbers.paymentMethodTypeValueFilter(object):include, up to 10 method types.reserveOrderNumberFilter(object):include, up to 30 reserve order numbers.sort(object):attributeanddirection. The only attributes the service accepts areinvoiceIssuedDateandinvoiceDueDate; anything else answers400 Invalid input because of error(s): [sort:attribute field is invalid]. Those are the names the answer uses, not the filter names:invoiceDate,issuedDate,dueDate,amountDueandstatusare all refused.maxResults(integer): page size.nextToken(string): token from a previous answer.aggregation(object):attributeandgroupBy, to total rather than list.
The
includefilters also acceptqueryTermMatchType, which decides how the term is matched.- Returns
ApiResponse with
invoiceSummaries. Each entry is richer than whatInvoices.list_invoicesreturns and shaped differently: dates come as"2026-10-26"rather than"20261026", and most fields are{"code": ..., "value": ...}pairs rather than plain strings. A summary carriesid,invoiceIssuedDate,invoiceDueDate,amountDueandremainingAmountDue(each with acurrencyCodeand avalue),status,paymentStatus,country,product,paymentMethodType,invoicingLevelandfxInformation.
- list_billing_profiles(**kwargs) ApiResponse
Lists the billing profiles of the account.
A billing profile decides who gets invoiced and with which payment method, so this is the starting point before reading usages or creating a statement.
Request Body (optional)
filters(object): narrow the list.maxResults(integer): page size.nextToken(string): token from a previous answer.
Warning
The service refuses marketplace accounts. Called from a regional seller account it answers
400 The API doesnot support marketplace accounts. It wants a Global, Manager or Sponsored Ads account.- Returns
ApiResponse with the profiles and the token for the next page.
- list_billing_profile_usages(**kwargs) ApiResponse
Lists which billing profile each country uses.
The answer links a country to a
billingProfileId. WithexpandBillingProfileit carries the whole profile rather than the identifier.Request Body (optional)
expandBillingProfile(boolean): return the full profile, not only its id.expandFallbackBillingProfile(boolean): also return the profile that would apply if the main one could not be used.filters(object): narrow by country or profile.maxResults(integer): page size.nextToken(string): token from a previous answer.
Warning
Same account restriction as
list_billing_profiles, and the message names what it wants:only Global, Manager and Sponsored Ads marketplace accounts are supported.- Returns
ApiResponse with one entry per country and profile pairing.
- get_billing_document(documentId, **kwargs) ApiResponse
Reads one billing document.
Path
documentId(string): required.
Query
docType(string): required in practice, though the contract lists it as a plain parameter. Without it the service answers400 Value null at 'docType' failed to satisfy constraint.
- Returns
ApiResponse with the document.
- get_billing_profile_agreement_content(billingProfileAgreementContentId, **kwargs) ApiResponse
Reads the agreement text attached to a billing profile.
Path
billingProfileAgreementContentId(string): required.
Query
languageOfPreference(string): the language the text comes back in.
- Returns
ApiResponse with the agreement content.
- get_billing_statement(billingStatementRequestId, **kwargs) ApiResponse
Reports on a billing statement request.
The identifier comes from the route that creates the statement request, and this reads its progress or its result.
Note
The contract answers this read with
vnd.createbillingstatementsrequest.v1, the same media type the creation route uses. That is what it declares, odd as the name is.Path
billingStatementRequestId(string): required. Three names are in play for this one value: the contract calls itbillingStatementRequestId, the method takesbillingStatementRequestId, and a rejected call comes back namingbillingStatementId.
The error for a malformed value also mentions a
requestparameter the contract does not list.- Returns
ApiResponse with the state of that request.
- create_billing_statement(**kwargs) ApiResponse
Asks the service to generate a billing statement for a period.
The work is asynchronous. This answers a
requestId, andget_billing_statementreads the state of that request.Request Body (required)
startDate(string): required. The first day of the period.endDate(string): required. The last day of the period.locale(string): required. The language the statement comes back in.countryCodes(array): the countries to cover.format(string):CSVis the only value the contract lists.
- Returns
ApiResponse with the request identifier. The contract answers
207, a multi-status, not200.
- apply_billing_profile(**kwargs) ApiResponse
Links one or more countries to a billing profile.
The service calls this applying a profile: after it, the countries named charge through that profile.
Request Body (required)
billingProfileUsages(array): required. One entry per country and profile pairing, which reads back in the same shapelist_billing_profile_usagesreturns.
The contract does not describe the fields inside each entry, so read one back from
list_billing_profile_usagesbefore building a body here.Warning
Not exercised. Applying a profile changes how an account gets charged.
- Returns
ApiResponse. The contract answers
207, a multi-status, not200.
- create_billing_profiles(**kwargs) ApiResponse
Creates one or more billing profiles.
Request Body (required)
billingProfiles(array): required, between 0 and 100 entries. Each one describes a profile to create.
The contract names the list and stops there: the fields of an entry are not described. Read one back from
list_billing_profilesfor the shape, rather than guessing at it.Warning
Not exercised. Creating a billing profile changes how an account gets invoiced.
- Returns
ApiResponse. The contract answers
207, a multi-status, not200.
- update_billing_profiles(**kwargs) ApiResponse
Updates one or more billing profiles.
Request Body
billingProfiles(array): between 0 and 100 entries. Each one names a profile and the fields to change.
The same gap as
create_billing_profiles: the contract does not describe the fields inside an entry.Warning
Not exercised, for the same reason as the create route.
- Returns
ApiResponse. The contract answers
207, a multi-status, not200.
- create_payment_profiles(**kwargs) ApiResponse
Creates one or more payment profiles.
Request Body (required)
paymentProfiles(array): required. Each entry describes a profile: which payment methods to use and in what order.
The contract names the list and does not describe its entries. The shape of a payment method reads back from
get_payment_agreements, whose agreements carry apaymentProfileholdingpaymentMethodsordered bypriority.Warning
Not exercised. A payment profile decides where money is taken from.
- Returns
ApiResponse. The contract answers
207, a multi-status, not200.