Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Maxio Wallet Adjustments API
version: '1.0'
contact:
email: support@maxio.com
description: 'Operations tagged Wallet Adjustments 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 Adjustments
description: Wallet Adjustments post a signed correction against a specific grant, or against an overdraft, on a wallet's ledger. Adjustments are intended for support and operations corrections, and each adjustment requires a reason that is recorded on the ledger. For more information, see Understand Wallets.
paths:
/wallets/{wallet_id}/adjustments.json:
parameters: []
post:
tags:
- Wallet Adjustments
summary: createWalletAdjustment
description: 'Posts a signed correction against a specific grant (or, for an overdraft entry, against the overdraft): positive adds units to the grant, negative removes them. `reason` is required and is written to the ledger row''s `memo`. Writes exactly one ledger row, of kind `adjustment`.
Use `source_transaction_id` to name a specific `debit` row when you''re correcting one recorded consumption rather than the grant''s balance as a whole. When it names a grant-attributed debit, it''s recorded for audit only: naming it doesn''t change how `amount` is applied, and more than one adjustment may name the same row. When it names an overdraft entry, it switches the correction to the overdraft path described below.
An overdraft entry (a `debit` row with no `grant_id`, written when an `allow_negative` wallet consumes past its grants) can be corrected without a `grant_id`. That correction is credit-only, credits no grant, and is bounded by the usage the entry still records and by the overdraft the wallet still owes. Once a later grant has repaid the overdraft, correct that grant''s balance instead.
An adjustment corrects the ledger, so it works on the grant''s recorded remainder, `posted_remaining`, not on `remaining`, which on a metered wallet read through Read Wallet also subtracts usage not yet posted. Send `posted_remaining` back as `expected_remaining`; sending `remaining` on a metered wallet with pending usage returns `409`.
`expected_remaining` and `expected_source_corrections` are optional optimistic-concurrency checks; see their field descriptions. Use them when the correction''s `amount` was derived from a value read earlier that might have moved since.'
operationId: createWalletAdjustment
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/CreateWalletAdjustmentRequest'
- examples:
- adjustment:
grant_id: 9
amount: '10.0'
reason: Support credit for outage on 2026-07-30
contentMediaType: application/json
examples:
Example:
value:
adjustment:
grant_id: 9
amount: '10.0'
reason: Support credit for outage on 2026-07-30
required: false
responses:
'201':
description: The ledger row written, plus the wallet's new balance.
headers: {}
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/WalletGrantResultResponse'
- description: 'Returned by an adjustment: the ledger row written, plus the wallet''s new balance.'
examples:
- wallet_transactions:
- id: 44
wallet_id: 5
kind: adjustment
amount: '10.0'
grant_id: 9
source_transaction_id: null
source_corrections_total: null
balance_after: '60.0'
metered_from_at: null
metered_through_at: null
conversion_rate_applied: null
invoice_uid: null
memo: Support credit for outage on 2026-07-30
created_at: '2026-08-02T09:10:00Z'
balance: '60.0'
contentMediaType: application/json
examples:
Example:
value:
wallet_transactions:
- id: 44
wallet_id: 5
kind: adjustment
amount: '10.0'
grant_id: 9
source_transaction_id: null
source_corrections_total: null
balance_after: '60.0'
metered_from_at: null
metered_through_at: null
conversion_rate_applied: null
invoice_uid: null
memo: Support credit for outage on 2026-07-30
created_at: '2026-08-02T09:10:00Z'
balance: '60.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: 'Returned in two cases. A request with the same `Idempotency-Key` was still being processed when this retry''s wait for it timed out (`idempotency_request_in_progress`); retry with the same key once it finishes. Or the state the `amount` was derived from has moved: either the grant''s `posted_remaining` no longer matches `expected_remaining`, or the corrections already posted against `source_transaction_id` no longer sum to `expected_source_corrections`. Nothing is written. Reload and re-derive the amount.'
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"}'
- '{"errors":["The grant balance changed since this correction was prepared. Reload and try again."],"code":"grant_changed"}'
contentMediaType: application/json
examples:
IdempotencyRequestInProgress:
value:
errors:
- A request with this Idempotency-Key is still being processed
code: idempotency_request_in_progress
Example:
value:
errors:
- The grant balance changed since this correction was prepared. Reload and try again.
code: grant_changed
'422':
description: Validation failure, or an `Idempotency-Key` reused with a different request (`idempotency_key_mismatch`). Validation failures include a missing `reason`, a `reason` over 255 characters, a missing or not-found `grant_id`, a zero, malformed, or out-of-range `amount`, a negative adjustment exceeding the grant's `posted_remaining`, a positive adjustment exceeding the grant's `original`, a malformed `expected_remaining` or `expected_source_corrections` (including an empty string, which is treated as malformed rather than omitted), a `source_transaction_id` not on this wallet or not a `debit` row, an overdraft correction that debits instead of credits ("Overdraft usage can only be corrected downward"), that exceeds the usage the entry still records ("Adjustment exceeds the usage this entry still records"), or that exceeds the overdraft the wallet still owes ("Adjustment exceeds the wallet's outstanding overdraft", followed by how much can still be corrected), a `grant_id` sent with an overdraft entry, and an archived 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":["Adjustment exceeds the grant''s remaining balance"],"code":"adjustment_exceeds_remaining"}'
contentMediaType: application/json
examples:
IdempotencyKeyMismatch:
value:
errors:
- This Idempotency-Key was already used with a different request
code: idempotency_key_mismatch
Example:
value:
errors:
- Adjustment exceeds the grant's remaining balance
code: adjustment_exceeds_remaining
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`.
WalletGrantResultResponse:
title: WalletGrantResultResponse
required:
- wallet_transactions
- balance
type: object
properties:
wallet_transactions:
type: array
items:
$ref: '#/components/schemas/WalletTransaction'
description: ''
balance:
type: string
description: The wallet's new balance, as a decimal string.
description: 'Returned by an adjustment: the ledger row written, plus the wallet''s new balance.'
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.
CreateWalletAdjustmentRequest:
title: CreateWalletAdjustmentRequest
required:
- adjustment
type: object
properties:
adjustment:
$ref: '#/components/schemas/Adjustment'
description: A signed correction to a specific grant's balance, or to an overdraft entry's usage, intended for support and ops use.
Adjustment:
title: Adjustment
required:
- amount
- reason
type: object
properties:
amount:
oneOf:
- type: string
- type: integer
contentEncoding: int32
description: 'Signed: positive adds units to the grant, negative removes them. Bounded below by the grant''s `posted_remaining` (a correction can''t drive it negative) and above by the grant''s `original` (a correction can''t credit past what was originally granted). An out-of-bounds value is rejected rather than clamped. Zero is rejected. Without a `grant_id` (an overdraft correction), the amount must be positive, can''t exceed the usage the overdraft entry still records, and can''t exceed the overdraft the wallet still owes. 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:
- '10.0'
reason:
maxLength: 255
type: string
description: Required. Lands on the resulting ledger row's `memo`.
grant_id:
type:
- integer
- 'null'
description: 'The grant to correct. Must belong to this wallet. Required unless `source_transaction_id` names an overdraft entry (a `debit` with no `grant_id`, written when an `allow_negative` wallet consumes past its grants). For an overdraft entry, omit it: sending one returns `422`, and the correction credits the wallet''s outstanding overdraft instead of any grant.'
contentEncoding: int32
source_transaction_id:
type:
- integer
- 'null'
description: '(Optional) The `debit` row this correction is fixing. Must belong to this wallet, and must name a row of kind `debit`; grant and adjustment rows are append-only history, corrected by posting a further adjustment rather than by pointing at them. For a grant-attributed debit, it''s recorded on the resulting ledger row for audit only: it does not change how `amount` is applied, and more than one adjustment may name the same row. For an overdraft entry, it decides the path: omit `grant_id`, and the correction is credit-only, bounded by the usage the entry still records and by the overdraft the wallet still owes.'
contentEncoding: int32
expected_remaining:
type:
- string
- 'null'
description: '(Optional) An optimistic-concurrency check for a caller whose `amount` was derived from the grant''s own remainder. Send the grant''s `posted_remaining`, not its `remaining`: on a metered wallet read through [Read Wallet]($e/Wallets/readWallet), `remaining` also subtracts usage not yet posted, so it can differ from what the adjustment checks. If given and the grant''s current `posted_remaining` no longer matches, the request is rejected with `409` and nothing is written. Compared numerically, so `"100"` and `"100.00000000"` both match a `posted_remaining` of `100`. Omit the field entirely to skip the check; sending it as an empty string is treated as a malformed value (`422`), not as an omission.'
expected_source_corrections:
type:
- string
- 'null'
description: '(Optional) An optimistic-concurrency check for a caller whose `amount` was derived from a usage entry, sent together with `source_transaction_id`: the entry''s `source_corrections_total` as the caller last read it (`"0"` if none). If the sum the server computes no longer matches, the request is rejected with `409` and nothing is written. This is what catches a correction posted between that read and this request. Ignored unless `source_transaction_id` is also given.'
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)