Skip to content

Read what the platform made and spent on a merchant account in a month

GET
/v1/merchant-accounts/{merchant_account_id}/platform-earnings
curl --request GET \
--url 'https://api.aerandil.com/v1/merchant-accounts/2489E9AD-2EE2-8E00-8EC9-32D5F69181C0/platform-earnings?month=example' \
--header 'Authorization: Bearer <token>'

A fold over the platform’s own balance transactions for one hotel’s merchant account in the house’s calendar month (platform_ledger_line, read off Stripe with the platform’s key by the platform-ledger worker): the guest’s money captured, refunds, the application fees earned, Stripe’s processing fees paid, what chargebacks cost after pass-through (dispute_costs), the net of every line (net_platform_earning, to the penny) and what the fee and dispute lines do not explain (unexplained — a refund not reversed from the hotel, a capture never transferred). variance is Stripe’s actual fee less the class estimate over the payments carrying both; variance_gaps counts the payments missing one side. The platform operator’s read (tenant_admin:write): the margin and the variance are the platform’s, never the hotel’s — the night-audit close shows the hotel only what it paid.

merchant_account_id
required
string format: uuid

The property’s merchant account.

month
required
string
/^[0-9]{4}-[0-9]{2}$/

The house’s calendar month, YYYY-MM.

The month’s platform earnings on the account.

Media typeapplication/json
object
case_count
integer
from
required
string format: date
line_count
required
integer
merchant_account_id
required
string format: uuid
month
required
string
payment_count
integer
property_id
string format: uuid
to
required
string format: date
totals
required
Array<object>
object
currency
string
dispute_costs
object
amounts_recovered
string format: decimal
amounts_withdrawn
string format: decimal
carried
string format: decimal
fees_charged
string format: decimal
fees_recovered
string format: decimal
gross_captured
string format: decimal
net_platform_earning
string format: decimal
platform_fees_earned
string format: decimal
processor_fees_paid
string format: decimal
refunded
string format: decimal
unexplained
string format: decimal
variance
object
estimates
string format: decimal
payments_compared
integer
processor_fees
string format: decimal
variance
string format: decimal
unmatched_count
required
integer
variance_gaps
required
object
missing_actual
integer
missing_estimate
integer
other_currency
integer
Examplegenerated
{
"case_count": 1,
"from": "2026-04-15",
"line_count": 1,
"merchant_account_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"month": "example",
"payment_count": 1,
"property_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0",
"to": "2026-04-15",
"totals": [
{
"currency": "example",
"dispute_costs": {
"amounts_recovered": "example",
"amounts_withdrawn": "example",
"carried": "example",
"fees_charged": "example",
"fees_recovered": "example"
},
"gross_captured": "example",
"net_platform_earning": "example",
"platform_fees_earned": "example",
"processor_fees_paid": "example",
"refunded": "example",
"unexplained": "example",
"variance": {
"estimates": "example",
"payments_compared": 1,
"processor_fees": "example",
"variance": "example"
}
}
],
"unmatched_count": 1,
"variance_gaps": {
"missing_actual": 1,
"missing_estimate": 1,
"other_currency": 1
}
}
Cache-Control
string

Always no-store. Object and link state is live data and is never cacheable.

The bearer authenticated but does not hold the scope this operation requires.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

No such object in the caller’s tenant — which is also the answer when it exists in another tenant, by design.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}

month is missing or not YYYY-MM.

Media typeapplication/json

Structured error wrapper. Every non-2xx response from any Aerandil endpoint serialises to this shape; the HTTP status carries the failure class (4xx/5xx), the body adds a stable code for programmatic dispatch plus a human-readable message.

object
error
required
object
code
required

Stable, programmatic error code (e.g. unauthorized, forbidden, not_found, invalid_body, invalid_url, precondition_failed, no_secondary_key). Clients dispatch on code, not on the message (which may be localised or contextualised in future versions).

string
instance_id

Request-id correlation handle echoed on the request-id response header — support teams correlate without scraping logs.

string
message
required

Human-readable explanation of the failure.

string
parameters

Per-error structured detail. The shape varies by code (e.g. forbidden_action carries {"action": "..."}; precondition_failed carries {"current_version": N}).

Examplegenerated
{
"error": {
"code": "example",
"instance_id": "example",
"message": "example",
"parameters": "example"
}
}