Skip to content

Get an invoice

GET
/api/v1/organizations/{orgID}/billing/invoices/{invoiceID}
curl --request GET \
--url https://api.aetherplatform.cloud/api/v1/organizations/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/billing/invoices/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0 \
--header 'Authorization: Bearer <token>'
orgID
required
string format: uuid

Organization UUID.

invoiceID
required
string format: uuid

Invoice UUID.

The invoice, including its itemized line items.

Media typeapplication/json

A single invoice with its itemized line items. All Invoice fields are present at the top level; line_items is the ordered breakdown (subscription lines first, then autoscaling usage).

object
id
required
string format: uuid
invoice_number
required

The customer-facing identity, AE-YYYY-NNNN, from a gapless series. Assigned once at issue and never reused; a re-issue gets the next number and the voided invoice keeps its own.

string
org_id
required
string format: uuid
period_start
required
string format: date-time
period_end
required
string format: date-time
subtotal_cents
required
integer format: int64
tax_cents
required
integer format: int64
tax_rate_bp
required

The tax rate applied, in basis points (1900 = 19 %); 0 when no tax is charged.

integer
tax_note
required

The statement printed on the invoice explaining the tax treatment (for example why no VAT is charged); empty when there is none.

string
total_cents
required

The amount owed, and exactly the amount a payment charges — there is no separate charged amount.

integer format: int64
status
required

issued until paid, then paid; void for an invoice that was re-issued (see replaced_by_invoice_id). A failed payment is not a status: the invoice stays issued and the failure is recorded in last_payment_error. An invoice whose total is 0 is paid from the moment it is issued. Clients must tolerate a value they do not know.

string
issuer
required

The selling entity as it was when the invoice was issued. A historical record: every field is always present, as an empty string when it has no value.

object
legal_name
required
string
address_line1
required
string
address_line2
required
string
city
required
string
postal_code
required
string
country_code
required
string
company_number
required
string
vat_registered
required

Whether the issuer was VAT-registered at issue time. It does not by itself mean VAT was charged — see the invoice’s tax_rate_bp.

boolean
vat_id
required
string
tax_note
required
string
buyer
required

The customer as they were when the invoice was issued. A historical record: every field is always present, as an empty string when it has no value. Contains personal data (names, addresses, email).

object
org_id
required
string format: uuid
name
required
string
customer_type
required
string
legal_name
required
string
first_name
required
string
last_name
required
string
billing_address
required
string
primary_contact
required
string
billing_email
required
string
vat_id
required
string
country_code
required
string
pdf_url

The address of a hosted PDF, when one exists; omitted otherwise. No invoice carries one today.

string | null
created_at
required
string format: date-time
paid_at

When the invoice was paid; omitted until it is.

string format: date-time
payment_attempts
required

How many payment attempts have been started for this invoice (automatic and manual together). Copied onto a replacement when the invoice is re-issued.

integer
last_payment_error

A sanitised decline code or short message from the most recent failed attempt — never a raw payment-provider error. Omitted when no attempt has failed; cleared when the invoice is paid.

string
last_payment_at

When the most recent payment attempt was made; omitted when there has been none.

string format: date-time
payment_in_flight
required

True while a payment for this invoice has been started and has not reached a final outcome (for example while a 3-D Secure challenge is open). No second payment is started while this is true; the pay endpoint answers requires_action or processing instead.

boolean
discount_id

The organization’s discount (OrgDiscount.id) that was active when the invoice was issued, whether or not its scope matched any line; omitted when there was none. Provenance only — what the discount did is in each line’s discount_cents.

string format: uuid
issued_at
required

When this document was issued. A replacement carries its own, later issued_at.

string format: date-time
due_clock_start_at
required

Where the payment period counts from. Equal to issued_at for an invoice issued at month close, and copied unchanged onto a replacement, so re-issuing an invoice never extends the time to pay.

string format: date-time
voided_at

When the invoice was voided; omitted unless status is void.

string format: date-time
replaces_invoice_id

On a replacement: the id of the voided invoice it replaces. Omitted on an invoice issued at month close.

string format: uuid
replaced_by_invoice_id

On a voided invoice: the id of the invoice that replaced it — the one to show and to pay. Omitted otherwise.

string format: uuid
line_items
required
Array<object>
object
id
required
string format: uuid
invoice_id
required
string format: uuid
position
required

Stable render order within the invoice (0-based).

integer
description
required
string
resource_type

What a usage line meters: vcpu, memory or disk (node resources, which carry node_size and node_hours), or registry, storage_block or storage_rwx (storage usage, no node dimension). Null on subscription lines.

string | null
quantity

Billed resource-hours on a usage line: size × hours, i.e. node_size × node_hours where those are present.

number | null
unit
string | null
unit_price_eur

The per-resource-hour rate the line was priced at.

number | null
amount_cents
required

The NET — the line as it counts towards the invoice subtotal: gross_amount_cents − discount_cents.

integer format: int64
gross_amount_cents
required

The line at list price, rounded to cents once. Unchanged when an invoice is re-issued with a discount.

integer format: int64
discount_cents
required

The discount on this line in cents (0 when none applies): the organization’s discount at issue time, applied to the lines its scope matches by charge_kind.

integer format: int64
charge_kind

What kind of charge the line is, and the key a discount’s scope is matched against: a subscription kind (node_pool, control_plane, plan, plan_overage, public_ip, loadbalancer) or, on a usage line, its resource type (vcpu, memory, disk, registry, storage_block, storage_rwx). Omitted on lines of invoices issued before this field existed; such a line is matched only by a discount that covers everything.

string | null
node_size

The per-node quantity of the resource on a node usage line (4 for a 4-vCPU node). Omitted — never 0, and in practice never null — on a line with no node dimension (subscriptions, storage) and on lines of invoices issued before this field existed. Contrast AutoscalingRollupLine.node_size, which is always present and 0 there.

number | null
node_hours

How many node-hours ran at node_size; a node usage line reads as node_size × node_hours. Omitted (never 0) under the same conditions as node_size.

integer | null
unit_price_month_eur

The rate card’s price per unit per MONTH as it was when the invoice was issued — the published list price behind unit_price_eur (which is this divided by 730 hours). Present on usage lines; omitted on subscription lines and on lines of invoices issued before this field existed.

number | null
Examplegenerated
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"invoice_number": "example",
"org_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"period_start": "2026-04-15T12:00:00Z",
"period_end": "2026-04-15T12:00:00Z",
"subtotal_cents": 1,
"tax_cents": 1,
"tax_rate_bp": 1,
"tax_note": "example",
"total_cents": 1,
"status": "example",
"issuer": {
"legal_name": "example",
"address_line1": "example",
"address_line2": "example",
"city": "example",
"postal_code": "example",
"country_code": "example",
"company_number": "example",
"vat_registered": true,
"vat_id": "example",
"tax_note": "example"
},
"buyer": {
"org_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"name": "example",
"customer_type": "example",
"legal_name": "example",
"first_name": "example",
"last_name": "example",
"billing_address": "example",
"primary_contact": "example",
"billing_email": "example",
"vat_id": "example",
"country_code": "example"
},
"pdf_url": "example",
"created_at": "2026-04-15T12:00:00Z",
"paid_at": "2026-04-15T12:00:00Z",
"payment_attempts": 1,
"last_payment_error": "example",
"last_payment_at": "2026-04-15T12:00:00Z",
"payment_in_flight": true,
"discount_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"issued_at": "2026-04-15T12:00:00Z",
"due_clock_start_at": "2026-04-15T12:00:00Z",
"voided_at": "2026-04-15T12:00:00Z",
"replaces_invoice_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"replaced_by_invoice_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"line_items": [
{
"id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"invoice_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"position": 1,
"description": "example",
"resource_type": "example",
"quantity": 1,
"unit": "example",
"unit_price_eur": 1,
"amount_cents": 1,
"gross_amount_cents": 1,
"discount_cents": 1,
"charge_kind": "example",
"node_size": 1,
"node_hours": 1,
"unit_price_month_eur": 1
}
]
}

Missing or invalid credentials.

Media typeapplication/json
object
error
required
object
code
required

A stable, machine-readable error code.

string
message
required
string
details
Array<object>
object
field
required
string
code
required
string
message
required
string
status_url

The platform status page (https://status.aetherplatform.cloud). Present on 5xx answers written by the API’s error writer and on no other; absent, not null, on 4xx.

string format: uri
decline_code

The payment provider’s decline code. Present only on 402 payment_declined; it is its own field and is never folded into message.

string
invoice_id

Present on exactly these errors of the invoice pay and pay/confirm endpoints: 402 payment_declined, 402 payment_method_required, 409 invoice_already_paid, 409 invoice_not_issued, 409 invoice_below_minimum, 409 payment_not_in_flight, and 409 invoice_void when the void invoice was replaced. It is the id of the live invoice, which after a re-issue is the replacement and not the id in the request URL (on 409 invoice_void from pay/confirm it is the replacement’s id). Absent on every other error — 400 (including discount_code_invalid), 403, 404, the discount_* 409s, 409 invoice_void with no replacement (nothing live to name), every 5xx and 503 code — and never null.

string format: uuid
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": [
{
"field": "example",
"code": "example",
"message": "example"
}
],
"status_url": "https://example.com",
"decline_code": "example",
"invoice_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
}
}

Refused by the organization role policy (see Authorization in the API description). error.code is forbidden when the caller is not a member of the organization (or the API token belongs to another organization), insufficient_role when the caller’s organization role is below the operation’s minimum role, and token_not_permitted when the request was authenticated with an API token on an operation API tokens may not use (the API Tokens operations; the handler-gated operations named in the API description: deleting the organization, changing a member’s role or payment_mode, paying an invoice including its confirm step, and discounts; and for a cluster-pinned machine token every operation except the loadbalancer-ips and loadbalancer-vms operations). email_unverified when a portal user’s e-mail address is not verified (see Authentication).

Media typeapplication/json
object
error
required
object
code
required

A stable, machine-readable error code.

string
message
required
string
details
Array<object>
object
field
required
string
code
required
string
message
required
string
status_url

The platform status page (https://status.aetherplatform.cloud). Present on 5xx answers written by the API’s error writer and on no other; absent, not null, on 4xx.

string format: uri
decline_code

The payment provider’s decline code. Present only on 402 payment_declined; it is its own field and is never folded into message.

string
invoice_id

Present on exactly these errors of the invoice pay and pay/confirm endpoints: 402 payment_declined, 402 payment_method_required, 409 invoice_already_paid, 409 invoice_not_issued, 409 invoice_below_minimum, 409 payment_not_in_flight, and 409 invoice_void when the void invoice was replaced. It is the id of the live invoice, which after a re-issue is the replacement and not the id in the request URL (on 409 invoice_void from pay/confirm it is the replacement’s id). Absent on every other error — 400 (including discount_code_invalid), 403, 404, the discount_* 409s, 409 invoice_void with no replacement (nothing live to name), every 5xx and 503 code — and never null.

string format: uuid
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": [
{
"field": "example",
"code": "example",
"message": "example"
}
],
"status_url": "https://example.com",
"decline_code": "example",
"invoice_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
}
}

The requested resource was not found.

Media typeapplication/json
object
error
required
object
code
required

A stable, machine-readable error code.

string
message
required
string
details
Array<object>
object
field
required
string
code
required
string
message
required
string
status_url

The platform status page (https://status.aetherplatform.cloud). Present on 5xx answers written by the API’s error writer and on no other; absent, not null, on 4xx.

string format: uri
decline_code

The payment provider’s decline code. Present only on 402 payment_declined; it is its own field and is never folded into message.

string
invoice_id

Present on exactly these errors of the invoice pay and pay/confirm endpoints: 402 payment_declined, 402 payment_method_required, 409 invoice_already_paid, 409 invoice_not_issued, 409 invoice_below_minimum, 409 payment_not_in_flight, and 409 invoice_void when the void invoice was replaced. It is the id of the live invoice, which after a re-issue is the replacement and not the id in the request URL (on 409 invoice_void from pay/confirm it is the replacement’s id). Absent on every other error — 400 (including discount_code_invalid), 403, 404, the discount_* 409s, 409 invoice_void with no replacement (nothing live to name), every 5xx and 503 code — and never null.

string format: uuid
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": [
{
"field": "example",
"code": "example",
"message": "example"
}
],
"status_url": "https://example.com",
"decline_code": "example",
"invoice_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"
}
}