Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Maxio Wallet Transactions API
version: '1.0'
contact:
email: support@maxio.com
description: 'Operations tagged Wallet Transactions across 2 of this provider''s published API definitions: maxio-advanced-billing-openapi31json.json, maxio-advanced-billing-openapi.yml. Each path carries the servers of the definition it was published in.'
servers:
- url: https://{site}.chargify.com
description: Default Advanced Billing environment hosted in US. Valid for the majority of our customers.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
- url: https://events.chargify.com/{site}
description: Default Advanced Billing environment hosted in US. Valid for the majority of our customers.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
- url: https://{site}.ebilling.maxio.com
description: Advanced Billing environment hosted in EU. Use only when you requested EU hosting for your AB account.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
security:
- BasicAuth: []
tags:
- name: Wallet Transactions
description: Use Wallet Transactions to fund a wallet with a one-time grant, consume units with a direct debit, and read the wallet's append-only ledger. For more information, see Understand Wallets.
paths:
/wallets/{wallet_id}/transactions.json:
parameters: []
get:
tags:
- Wallet Transactions
summary: listWalletTransactions
description: Lists the wallet's append-only ledger, newest first, paginated.
operationId: listWalletTransactions
parameters:
- name: wallet_id
in: path
description: The Advanced Billing id of the wallet.
required: true
schema:
type: integer
contentEncoding: int32
- name: page
in: query
description: 'Result records are organized in pages. By default, the first page of results is displayed. The page parameter specifies a page number of results to fetch. You can start navigating through the pages to consume the results. You do this by passing in a page parameter. Retrieve the next page by adding ?page=2 to the query string. If there are no results to return, then an empty result set will be returned.
Use in query `page=1`.'
style: form
explode: true
schema:
minimum: 1.0
type: integer
contentEncoding: int32
default: 1
examples:
- 1
- name: per_page
in: query
description: 'This parameter indicates how many records to fetch in each request. Default value is 20. The maximum allowed values is 200; any per_page value over 200 will be changed to 200.
Use in query `per_page=200`.'
style: form
explode: true
schema:
maximum: 200.0
type: integer
contentEncoding: int32
default: 20
examples:
- 50
responses:
'200':
description: OK
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletTransactionsListResponse'
- examples:
- wallet_transactions:
- id: 41
wallet_id: 5
kind: debit
amount: '-30.0'
grant_id: 9
source_transaction_id: null
source_corrections_total: '0.0'
balance_after: '0.0'
metered_from_at: null
metered_through_at: null
conversion_rate_applied: null
invoice_uid: null
memo: null
created_at: '2026-08-01T09:30:00Z'
meta:
total_count: 1
current_page: 1
total_pages: 1
per_page: 20
contentMediaType: application/json
examples:
Example:
value:
wallet_transactions:
- id: 41
wallet_id: 5
kind: debit
amount: '-30.0'
grant_id: 9
source_transaction_id: null
source_corrections_total: '0.0'
balance_after: '0.0'
metered_from_at: null
metered_through_at: null
conversion_rate_applied: null
invoice_uid: null
memo: null
created_at: '2026-08-01T09:30:00Z'
meta:
total_count: 1
current_page: 1
total_pages: 1
per_page: 20
'403':
description: Forbidden. The response body is plain text (`403 Forbidden`), not JSON. Returned when the Wallets feature isn't enabled for the site.
headers: {}
content: {}
'404':
description: Not Found
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
contentMediaType: application/json
deprecated: false
post:
tags:
- Wallet Transactions
summary: createWalletTransaction
description: 'Grants units to the wallet, or debits units from it, depending on `kind`. `amount` is always sent positive, and `kind` determines the direction written to the ledger.
**`kind: grant`**: a one-time manual top-up. On a non-negative balance, this creates a grant and writes one ledger row. On a negative balance, it repays the overdraft first (a `kind: grant` row with `grant_id: null`, for the repaid amount), then creates the grant: its `original` is always the full `amount` sent, and its `remaining` is what''s left after the overdraft was repaid, which is `0` if the overdraft absorbed the whole top-up. The grant row is still written, and its `amount` is that `remaining`, not `original`, so the ledger rows sum to the balance change. A grant may carry `expires_at`; a debit may not.
**`kind: debit`**: direct consumption. Drains grants earliest-expiration-first, one `kind: debit` row per grant touched, plus any overdue expiration rows this same call triggers first (see below):
- Under the wallet''s default `hard_stop_overflow: discard`, the drain is capped at the available balance. For a metered wallet, that cap is the live metered balance, not the stored one, so a debit can drain less than its stored balance would suggest, or even drain nothing at all (`201` with `drained_amount: "0.0"`) if live usage has already consumed what the ledger hadn''t caught up to yet. A debit against a wallet whose *stored* balance is already zero or negative (`discard` only ever reaches zero) returns `422 "Wallet is depleted"`. Before that failure is returned, this call still expires any grants that were already overdue, so a `422` response can still leave new `kind: expiration` rows written.
- Under `hard_stop_overflow: allow_negative`, the full amount is deducted. The excess past the wallet''s grants is booked as one overdraft row with `grant_id: null`, `rejected_amount` is always `"0.0"`, and the balance goes negative.'
operationId: createWalletTransaction
parameters:
- name: wallet_id
in: path
description: The Advanced Billing id of the wallet.
required: true
schema:
type: integer
contentEncoding: int32
- name: Idempotency-Key
in: header
description: 'A key you generate, such as a UUID, that makes retrying this request safe. 1 to 255 printable ASCII characters; surrounding double quotes are ignored. Keys are scoped to your site and kept for at least 24 hours.
The first request with a key runs normally. A retry with the same key, method, path and query string, and a byte-identical body returns the stored status and body of that first request without running it again. The same key with a different request returns `422` (`idempotency_key_mismatch`). A retry that arrives while the first request is still running waits for it to finish, and returns `409` (`idempotency_request_in_progress`) only if that wait times out; on Create Wallet Purchase the `409` is immediate. Only successful responses are stored, so a failed request can be retried with the same key. When this header is sent, `uniqueness_token` is not checked.
See [Idempotent retries](page:introduction/basic-concepts/wallets#idempotent-retries) for the details, including how wallet purchases differ.'
schema:
maxLength: 255
minLength: 1
type: string
requestBody:
description: ''
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/CreateWalletTransactionRequest'
- examples:
- '{"wallet_transaction":{"kind":"grant","amount":"100.0","memo":"Manual top-up"}}'
- '{"wallet_transaction":{"kind":"debit","amount":"30.0"}}'
contentMediaType: application/json
examples:
Grant:
value:
wallet_transaction:
kind: grant
amount: '100.0'
memo: Manual top-up
Debit:
value:
wallet_transaction:
kind: debit
amount: '30.0'
required: false
responses:
'201':
description: 'Transaction applied. For `kind: grant`, the ledger row(s) written plus the new balance. For `kind: debit`, one row per grant touched plus the requested/drained/rejected accounting and the new balance.'
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletTransactionResultResponse'
- description: Returned by [Create Wallet Transaction]($e/Wallet%20Transactions/createWalletTransaction). `wallet_transactions` and `balance` are always present. `requested_amount`, `drained_amount`, and `rejected_amount` are present only when the request's `kind` was `debit`.
examples:
- '{"wallet_transactions":[{"id":42,"wallet_id":5,"kind":"grant","amount":"100.0","grant_id":13,"source_transaction_id":null,"source_corrections_total":null,"balance_after":"250.0","metered_from_at":null,"metered_through_at":null,"conversion_rate_applied":null,"invoice_uid":null,"memo":"Manual top-up","created_at":"2026-08-02T09:00:00Z"}],"balance":"250.0"}'
- '{"wallet_transactions":[{"id":43,"wallet_id":5,"kind":"debit","amount":"-30.0","grant_id":9,"source_transaction_id":null,"source_corrections_total":"0.0","balance_after":"0.0","metered_from_at":null,"metered_through_at":null,"conversion_rate_applied":null,"invoice_uid":null,"memo":null,"created_at":"2026-08-02T09:05:00Z"}],"requested_amount":"100.0","drained_amount":"30.0","rejected_amount":"70.0","balance":"0.0"}'
contentMediaType: application/json
examples:
Grant:
value:
wallet_transactions:
- id: 42
wallet_id: 5
kind: grant
amount: '100.0'
grant_id: 13
source_transaction_id: null
source_corrections_total: null
balance_after: '250.0'
metered_from_at: null
metered_through_at: null
conversion_rate_applied: null
invoice_uid: null
memo: Manual top-up
created_at: '2026-08-02T09:00:00Z'
balance: '250.0'
Debit:
value:
wallet_transactions:
- id: 43
wallet_id: 5
kind: debit
amount: '-30.0'
grant_id: 9
source_transaction_id: null
source_corrections_total: '0.0'
balance_after: '0.0'
metered_from_at: null
metered_through_at: null
conversion_rate_applied: null
invoice_uid: null
memo: null
created_at: '2026-08-02T09:05:00Z'
requested_amount: '100.0'
drained_amount: '30.0'
rejected_amount: '70.0'
balance: '0.0'
'400':
description: The `Idempotency-Key` header is empty, longer than 255 characters, or contains characters other than printable ASCII. Nothing is written.
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
examples:
- errors:
- Idempotency-Key must be 1 to 255 printable ASCII characters
code: idempotency_key_invalid
contentMediaType: application/json
examples:
IdempotencyKeyInvalid:
value:
errors:
- Idempotency-Key must be 1 to 255 printable ASCII characters
code: idempotency_key_invalid
'403':
description: Forbidden. The response body is plain text (`403 Forbidden`), not JSON. Returned when the Wallets feature isn't enabled for the site.
headers: {}
content: {}
'404':
description: Not Found
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
contentMediaType: application/json
'409':
description: A request with the same `Idempotency-Key` was still being processed when this retry's wait for it timed out (`idempotency_request_in_progress`). Nothing is written; retry with the same key once it finishes.
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
examples:
- errors:
- A request with this Idempotency-Key is still being processed
code: idempotency_request_in_progress
contentMediaType: application/json
examples:
IdempotencyRequestInProgress:
value:
errors:
- A request with this Idempotency-Key is still being processed
code: idempotency_request_in_progress
'422':
description: 'Validation failure, or an `Idempotency-Key` reused with a different request (`idempotency_key_mismatch`). Validation failures include an unrecognized `kind`, a missing `wallet_transaction` root, a malformed, non-positive, or out-of-range `amount`, a memo over 255 characters, `expires_at` sent with `kind: debit`, a malformed or past-dated `expires_at`, an archived wallet, and, for `kind: debit` only, a depleted wallet.'
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
examples:
- '{"errors":["This Idempotency-Key was already used with a different request"],"code":"idempotency_key_mismatch"}'
- '{"errors":["Wallet is depleted"],"code":"wallet_depleted"}'
contentMediaType: application/json
examples:
IdempotencyKeyMismatch:
value:
errors:
- This Idempotency-Key was already used with a different request
code: idempotency_key_mismatch
Example:
value:
errors:
- Wallet is depleted
code: wallet_depleted
'500':
description: For a metered wallet, usage could be read but settling it against the ledger failed.
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
contentMediaType: application/json
'503':
description: 'For a metered wallet, live usage could not be read in time to compute the debit. Not returned for `kind: grant`.'
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletErrorResponse1'
- description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
contentMediaType: application/json
deprecated: false
servers:
- url: https://{site}.chargify.com
description: Default Advanced Billing environment hosted in US. Valid for the majority of our customers.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
- url: https://events.chargify.com/{site}
description: Default Advanced Billing environment hosted in US. Valid for the majority of our customers.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
- url: https://{site}.ebilling.maxio.com
description: Advanced Billing environment hosted in EU. Use only when you requested EU hosting for your AB account.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
- url: https://events.chargify.com/{site}
description: Advanced Billing environment hosted in EU. Use only when you requested EU hosting for your AB account.
variables:
site:
default: subdomain
description: The subdomain for your Advanced Billing site.
components:
schemas:
WalletErrorResponse1:
title: WalletErrorResponse1
required:
- errors
- code
type: object
properties:
errors:
type: array
items:
type: string
description: Human-readable messages. These may be reworded, so match on `code` instead.
code:
type: string
description: A stable, machine-readable reason, for example `wallet_depleted`, `wallet_not_found`, `wallet_product_not_found`, `price_point_archived`, `kind_invalid`, or `parameter_missing`. Failures that come from record validation, such as a field that fails a model rule, report `validation_failed`.
examples:
- wallet_depleted
invoice_uid:
type: string
description: 'Returned only by Create Wallet Purchase with `purchase_paid_but_uncredited`, `purchase_declined_invoice_open`, `purchase_invoice_left_open` and `purchase_payment_outcome_unknown`: the uid of the invoice the purchase created. Check it before buying again.'
invoice_number:
type: string
description: 'Returned alongside `invoice_uid`: the number of the invoice the purchase created.'
description: The JSON error body returned by every wallet, transaction, adjustment, purchase, and Wallet Product endpoint for `400`, `404`, `409`, `422`, `500`, and `503` responses. A `403` is not JSON; it is the plain text `403 Forbidden`.
Kind1:
title: Kind1
enum:
- grant
- debit
type: string
description: Determines the direction of the movement. The amount itself is always sent positive.
ListPublicKeysMeta:
title: ListPublicKeysMeta
type: object
properties:
total_count:
type: integer
contentEncoding: int32
current_page:
type: integer
contentEncoding: int32
total_pages:
type: integer
contentEncoding: int32
per_page:
type: integer
contentEncoding: int32
WalletTransaction:
title: WalletTransaction
type: object
properties:
id:
type: integer
description: The Advanced Billing id of the ledger row.
contentEncoding: int32
wallet_id:
type: integer
contentEncoding: int32
kind:
type: string
description: 'The kind of ledger row. Known values: `grant`, `debit`, `adjustment`, `initial_balance`, and `expiration`. More kinds are expected over time, so treat this as an open string and don''t fail on one you don''t recognize. Only `grant` and `debit` are accepted on [Create Wallet Transaction]($e/Wallet%20Transactions/createWalletTransaction). `adjustment` rows are written by [Create Wallet Adjustment]($e/Wallet%20Adjustments/createWalletAdjustment), `initial_balance` rows only by a seeded [Create Wallet]($e/Wallets/createWallet), and `expiration` rows only by the automatic expiry sweep that writes off an unconsumed grant once its `expires_at` passes.'
examples:
- grant
amount:
type: string
description: A decimal string, **signed** on this resource. Non-negative for grants, negative for debits and expirations, either sign for adjustments. A grant row written after an overdraft repayment carries only what was left after the repayment (possibly `"0.0"`), not the grant's `original`.
examples:
- '-30.0'
grant_id:
type:
- integer
- 'null'
description: 'The grant this row is attributed to. `null` for an overdraft row (a `kind: debit` row draining the below-zero portion of a balance, attributed to no grant), for an overdraft-repayment row (the `kind: grant` row that pays an existing negative balance back to zero, written before any remainder becomes a new grant), and for an overdraft correction (a `kind: adjustment` row posted against an overdraft entry, which credits no grant).'
contentEncoding: int32
source_transaction_id:
type:
- integer
- 'null'
description: For an `adjustment` row posted against a specific usage entry, the id of the `debit` row it corrects. `null` for every other kind, and for adjustments made against a grant's balance directly.
contentEncoding: int32
source_corrections_total:
type:
- string
- 'null'
description: For a `debit` row only, the signed sum (as a decimal string) of every adjustment posted against it so far (`"0.0"` when none). `null` for every other kind. The row's own `amount` is never rewritten, so a caller deriving the entry's corrected quantity nets this out of `amount`, and sends this value back as `expected_source_corrections` on a further correction.
balance_after:
type: string
description: The wallet's posted balance immediately after this row was applied, as a decimal string. Compare it with the wallet's `posted_balance`, not its `balance`.
metered_from_at:
type:
- string
- 'null'
description: For a row that closed a metered usage window (an hourly close, a depletion, or an expiry write-off), the start of that window. `null` on every other row.
contentEncoding: date-time
metered_through_at:
type:
- string
- 'null'
description: The end of the usage window this row closed. `null` on every other row.
contentEncoding: date-time
conversion_rate_applied:
type:
- string
- 'null'
description: The meter-to-wallet-unit conversion rate applied to compute this row's `amount`, as a decimal string. `null` on every other row.
invoice_uid:
type:
- string
- 'null'
description: 'The uid of the invoice behind a purchase''s rows: the grant-creating row and, when the purchase repaid an overdraft, the repayment row. `null` on every other row.'
memo:
type:
- string
- 'null'
description: Free-text note. For an `adjustment` row, carries the required `reason`.
created_at:
type: string
contentEncoding: date-time
description: One append-only row on the wallet's ledger. Always appears bare inside a `wallet_transactions` array, never wrapped in its own key.
WalletTransaction1:
title: WalletTransaction1
required:
- kind
- amount
type: object
properties:
kind:
allOf:
- $ref: '#/components/schemas/Kind1'
- description: Determines the direction of the movement. The amount itself is always sent positive.
amount:
oneOf:
- type: string
- type: integer
contentEncoding: int32
description: 'Always positive; `kind` determines the sign written to the ledger. Encoded as a decimal string with at most 8 fractional digits. Send fractional values as strings: a JSON number with a decimal point is rejected with `422`, because a double-precision float may already have lost precision before the request arrives.'
examples:
- '50.0'
memo:
maxLength: 255
type:
- string
- 'null'
expires_at:
type:
- string
- 'null'
description: 'An expiration for the grant this creates. Only accepted with `kind: grant`; sending it with `kind: debit` is rejected. Omit it for an evergreen grant. Accepts either a bare calendar date (`YYYY-MM-DD`), resolved to the end of that day in the site''s time zone, or a full timestamp. A calendar day that doesn''t exist, such as `2027-02-30`, is rejected with `422` rather than rolled into the next month.'
CreateWalletTransactionRequest:
title: CreateWalletTransactionRequest
required:
- wallet_transaction
type: object
properties:
wallet_transaction:
$ref: '#/components/schemas/WalletTransaction1'
WalletTransactionResultResponse:
title: WalletTransactionResultResponse
required:
- wallet_transactions
- balance
type: object
properties:
wallet_transactions:
type: array
items:
$ref: '#/components/schemas/WalletTransaction'
description: ''
requested_amount:
type: string
description: '`kind: debit` only. The amount that was requested, as a decimal string.'
drained_amount:
type: string
description: '`kind: debit` only. The amount actually drained from the wallet''s grants, as a decimal string.'
rejected_amount:
type: string
description: '`kind: debit` only, as a decimal string. Under `hard_stop_overflow: discard`, this is the requested amount minus what the wallet could cover (`"0.0"` on a full drain). Always `"0.0"` under `allow_negative`; nothing is rejected, and the balance goes negative instead.'
balance:
type: string
description: The wallet's new balance, as a decimal string.
description: Returned by [Create Wallet Transaction]($e/Wallet%20Transactions/createWalletTransaction). `wallet_transactions` and `balance` are always present. `requested_amount`, `drained_amount`, and `rejected_amount` are present only when the request's `kind` was `debit`.
WalletTransactionsListResponse:
title: WalletTransactionsListResponse
required:
- wallet_transactions
- meta
type: object
properties:
wallet_transactions:
type: array
items:
$ref: '#/components/schemas/WalletTransaction'
description: ''
meta:
$ref: '#/components/schemas/ListPublicKeysMeta'
securitySchemes:
BasicAuth:
type: http
description: The `username` is a Maxio Chargify API key. The `password` is `x`.
scheme: basic
x-refined-from:
- maxio-advanced-billing-openapi31json.json
- maxio-advanced-billing-openapi.yml
x-provenance:
method: harvested
publisher: Maxio
source: https://developers.maxio.com/static/exports/maxio-advanced-billing-openapi31json.json
note: split by refine-openapis from the provider's own published document, verified by fetch (openapi/_original/*.fetch.json);
stamped by stamp-openapi-provenance.py (roadmap#793)