Skip to main content

Channel Payouts

Beta

This endpoint is in beta and its shape may still change.

Overview

This resource represents channel movements — the money that channels such as Airbnb or Booking.com wire to us. Each channel payout is a single wire transfer, and this endpoint breaks it down to show how that transfer decomposes across the individual Bookings and account-level movements it covers.

A Channel Payout is the counterpart of the Smily-side Payouts endpoint. /payouts covers what Smily paid you and the Smily fees deducted from it. /channel_payouts covers the step before that: what the channel actually wired, and how it splits across the OTA commission, city tax and cleaning fees of each booking. If a booking received a smaller Smily payout than you anticipated, this endpoint holds the answer. The reduction may come from a deduction the channel applied to that booking directly, to another booking whose shortfall was balanced against it, or to the account as a whole.

For a walk-through of how the two endpoints fit together — including how to diagnose a payout that is smaller than expected — see the Understanding payouts guide.

An account-level movement is a line that belongs to the account rather than to any single booking. It covers channel activity that isn't tied to one reservation — an account-wide commission refund or deduction the OTA applies across the account. It is also used as a fallback: when a channel wires money for a booking that does not exist in Smily, the movement cannot be linked to a booking, so it is recorded at the account level instead. Account-level movements have a null booking_id and carry account_level: true.

Each channel payout carries two lists:

  • breakdown — one channel-agnostic line per movement. Each channel's native format is already merged for your convenience into a single shape here, so you never branch on the channel. Every line exposes the OTA decomposition, which is expected to account for the net:

    channel_price − ota_commission − ota_payment_charge_commission − withheld_city_tax = net_channel_payout

    Treat that as a reconciliation you can check, not an identity you can rely on. net_channel_payout_in_cents is always the verbatim amount the channel reported, never a recomputed value, so a line will not balance whenever the terms and the net disagree. Two known cases:

    • Booking.com correction and fee true-up rows, which restate a gross and a city tax that cancel out and then wire a small difference.
    • Airbnb reservation lines, where the price and the withheld tax are reconstructed by Smily rather than declared by the channel (see below). Where Smily's records and Airbnb's payout disagree, or where a multi-tranche stay's split rounds, the line will not close exactly.

    Always use net_channel_payout_in_cents as the amount and treat the other terms as the explanation of it.

    null means "not known", not "nothing" — so do not read a null term as zero when checking the chain. The one deliberate exception is ota_payment_charge_commission_in_cents on Airbnb, which is always null because Airbnb has no such line at all; there it genuinely means zero and the chain is evaluated with it as zero. Note also that a term being 0 is meaningful and is not the same as null: on an Airbnb line withheld_city_tax_in_cents: 0 means "reconstructed, and nothing was withheld".

  • allocations — the problem this solves: a channel sometimes applies a deduction — against one booking, or against the whole account — that lowers the total it wires. Smily's job is to distribute the wire per booking, so that deduction has to land somewhere: one or more other bookings are paid less to balance out what the OTA held back. allocations makes that redistribution explicit — for each negative movement, exactly how much was absorbed and by which bookings or account level movements.

    Concretely, each allocation names its source (booking with its id, or account with a null id) and lists in absorbed_by where the recoup was taken from. When no negative movements were recouped, allocations is an empty array.

note

This endpoint is read-only. Channel payouts are created and reconciled internally by Smily as OTA wires arrive; there is no way to create, update or delete them through the API.

Parameters

NameTypeRead/WriteDescription
idIntegerReadChannel Payout's id.
referenceStringReadThe channel's own payout reference (the identifier under which the OTA wired the money).
channelStringReadThe channel the payout originates from, derived from the reference prefix. airbnb when it matches a known Airbnb prefix, otherwise bcom — so bcom is a fallback rather than a positive match.
currencyStringReadPayout's currency code, list of codes described in enums section.
statusStringReadPayout's status. One of pending (received, not yet matched to an incoming wire transfer) or processed.
amount_in_centsIntegerReadThe net amount the channel wired for this payout, in cents.
breakdownArrayReadThe per-movement channel breakdown. See Breakdown line below.
allocationsArrayReadHow negative movements were recouped from other payouts. See Allocation below.
created_atTimeReadChannel Payout's create time.
updated_atTimeReadChannel Payout's update time.

Breakdown line

Each element of breakdown:

NameTypeDescription
booking_idIntegerThe Booking this movement belongs to. null for an account-level movement (e.g. an account correction).
account_levelBooleanWhether this is an account-level movement rather than a booking one. true implies booking_id is null.
payout_typeStringThe channel's native type for this movement (e.g. Reservation, Resolution, Correction). May be null when the channel's stored entry declares no type.
referenceStringThe channel's per-movement reference (e.g. the Airbnb confirmation code). May be null.
net_channel_payout_in_centsIntegerThe verbatim net amount of this movement, in cents. Signed — negative for adjustments/resolutions that reduce the payout.
channel_price_in_centsIntegerThe gross channel price before the OTA decomposition, in cents. May be null. On Booking.com it is the channel's declared gross; on Airbnb it is reconstructed by Smily — see How each channel fills these terms.
ota_commission_in_centsIntegerThe OTA commission withheld on this movement, in cents. May be null.
ota_payment_charge_commission_in_centsIntegerThe OTA payment-processing commission withheld, in cents. May be null. Always null on Airbnb, which has no such line.
withheld_city_tax_in_centsIntegerCity tax the channel withheld and remits itself, in cents. May be null. On Airbnb, 0 and null differ — see below.
cleaning_fee_in_centsIntegerThe cleaning fee portion of this movement, in cents. Always null on Booking.com, which does not itemise it.

payout_type values

On this endpoint payout_type is always the channel's own value, passed through verbatim. Smily does not normalise it, does not translate it, and does not restrict it to a known list — whatever the channel put on the movement is what you get.

Treat it as an opaque string, not an enum. The values below are the ones we have actually observed; they are a snapshot, not a contract. A channel can introduce a new type at any time and it will appear here without any change on our side, so code defensively: match the types you care about and pass the rest through rather than raising on an unrecognised value.

ChannelObserved on booking movementsObserved on account-level movements
AirbnbReservation, Resolution Adjustment, Resolution Payout, Pass Through Tot, Cancellation Fee
Booking.comReservation, RESERVATION, Net, NET, GROSS, Damage deposit, DAMAGE_POLICY, Commission adjustmentCommission adjustment, COMMISSION_CORRECTION, DOCUMENT_CLEARING, credit_note, customer_complaint

Two traps in that list:

  • Casing is not normalised. Booking.com sends both Reservation and RESERVATION, and both Net and NET, for the same thing. Compare case-insensitively.
  • Reservation is not unique to one meaning. Both channels use it, and on Payouts Smily uses the same word for a direct booking. It tells you what the movement is, never where it came from.

payout_type may also be null, when the channel's stored entry declares no type at all. A null type is not an error and the movement's amount is still valid — net_channel_payout_in_cents is unaffected.

How each channel fills these terms

The breakdown shape is the same for every channel, but the two channels do not report the same things, so which terms are declared, reconstructed or absent depends on channel.

FieldAirbnbBooking.com
net_channel_payout_in_centsverbatimverbatim
channel_price_in_centsreconstructed by Smily; null when it cannot bedeclared gross
ota_commission_in_centsdeclared (host_fee), else reconstructeddeclared
ota_payment_charge_commission_in_centsalways null — no such linedeclared
withheld_city_tax_in_centsreconstructed by Smily; 0, an amount, or nulldeclared
cleaning_fee_in_centsdeclaredalways null

What "reconstructed" means on Airbnb. Airbnb declares only the net, the host fee and the cleaning fee per movement — it never states the channel price or the withheld city tax. For reservation movements Smily reconstructs those two from its own records of the booking as they stood when that movement settled: the price the guest was charged, and the booking's own city-tax fees that the channel withheld. A stay that settles in several movements has each figure split across them.

Consequences worth coding for:

  • These terms are null on Airbnb movements that are not reservations — resolutions, adjustments and pass-throughs are served net-only, with no decomposition. That is not an error; there is nothing to reconstruct for a discrete adjustment amount.
  • They are also null when the reconstruction is not possible — for example when Smily holds no price history for the booking. null here means "unavailable", not "zero".
  • withheld_city_tax_in_cents: 0 is a positive statement: the booking was checked and withheld no city tax. Do not conflate it with null.
  • Because these terms come from Smily's records rather than the channel's message, an Airbnb reservation line can fail to close the chain — see the reconciliation note in the Overview.

Allocation

Each element of allocations describes one negative source movement and how it was recouped:

NameTypeDescription
typeStringThe source of the negative movement. One of booking or account.
booking_idIntegerThe source Booking's id when type is booking; null for account sources.
total_in_centsIntegerThe total amount recouped for this source, in cents. Always positive.
ota_in_centsIntegerThe OTA portion of the recouped amount, in cents. Always positive.
internal_fee_in_centsIntegerThe internal (Smily) fees portion of the recouped amount, in cents. Always positive.
absorbed_byArrayWhere the recoup was taken from. See Absorber below.

Absorber

Each element of an allocation's absorbed_by:

NameTypeDescription
typeStringThe kind of payout that absorbed the recoup. One of booking or account.
booking_idIntegerThe absorbing Booking's id when type is booking; null for the aggregated account entry.
total_in_centsIntegerThe total amount absorbed here, in cents. Always positive.
ota_in_centsIntegerThe OTA portion absorbed here, in cents. Always positive.
internal_fee_in_centsIntegerThe internal (Smily) fees portion absorbed here, in cents. Always positive.
original_ota_amount_in_centsIntegerThe absorbing payout's original OTA amount before the recoup was taken, in cents.

List channel payouts

List all channel payouts for the accounts the token is authorized for, most recent first.

GET /channel_payouts
response.json
{
"links": {},
"channel_payouts": [
{
"id": 8,
"reference": "G-NSGICZAZU4AFZ57LJ2CVTORKUYCG34ZR",
"channel": "airbnb",
"currency": "EUR",
"status": "pending",
"amount_in_cents": 109322,
"breakdown": [
{
"booking_id": 21,
"account_level": false,
"payout_type": "Reservation",
"reference": "HMMQ9BZAQK",
"net_channel_payout_in_cents": 112322,
"channel_price_in_cents": 144624,
"ota_commission_in_cents": 19822,
"ota_payment_charge_commission_in_cents": null,
"withheld_city_tax_in_cents": 12480,
"cleaning_fee_in_cents": 33044
},
{
"booking_id": 22,
"account_level": false,
"payout_type": "Resolution",
"reference": "RES-SRC-A",
"net_channel_payout_in_cents": -3000,
"channel_price_in_cents": null,
"ota_commission_in_cents": null,
"ota_payment_charge_commission_in_cents": null,
"withheld_city_tax_in_cents": null,
"cleaning_fee_in_cents": null
}
],
"allocations": [
{
"type": "booking",
"booking_id": 22,
"total_in_cents": 3000,
"ota_in_cents": 3000,
"internal_fee_in_cents": 0,
"absorbed_by": [
{
"type": "booking",
"booking_id": 21,
"total_in_cents": 3000,
"ota_in_cents": 3000,
"internal_fee_in_cents": 0,
"original_ota_amount_in_cents": 112322
}
]
}
],
"created_at": "2026-07-21T09:14:03.000Z",
"updated_at": "2026-07-21T09:14:03.000Z"
}
]
}

Search channel payouts

Search parameters allow to filter channel payouts by specified fields.

Example — a single channel payout by its channel reference:

GET /channel_payouts?reference=G-NSGICZAZU4AFZ57LJ2CVTORKUYCG34ZR

Example — every channel payout touching a given booking (e.g. its movements over time):

GET /channel_payouts?booking_id=21

Search Parameters

NameTypeDescription
idIntegerList of comma separated IDs. Returns only the channel payouts with these ids.
referenceStringReturns only the channel payout with this exact channel reference.
booking_idIntegerReturns only channel payouts whose breakdown touches this Booking.
updated_sinceTimeReturns only channel payouts updated since the given time. See the updated_since flow guide.
sortStringSort order. Defaults to -created_at,-id (most recent first).
note

Channel payouts are never deleted, so the deleted_ids array returned in meta alongside updated_since is always empty. It is present for consistency with the other endpoints.

Get a single channel payout

Returns a single channel payout identified by ID.

GET /channel_payouts/:channel_payout_id
response.json
{
"links": {},
"channel_payouts": [
{
"id": 8,
"reference": "G-NSGICZAZU4AFZ57LJ2CVTORKUYCG34ZR",
"channel": "airbnb",
"currency": "EUR",
"status": "pending",
"amount_in_cents": 109322,
"breakdown": [
{
"booking_id": 21,
"account_level": false,
"payout_type": "Reservation",
"reference": "HMMQ9BZAQK",
"net_channel_payout_in_cents": 112322,
"channel_price_in_cents": 144624,
"ota_commission_in_cents": 19822,
"ota_payment_charge_commission_in_cents": null,
"withheld_city_tax_in_cents": 12480,
"cleaning_fee_in_cents": 33044
},
{
"booking_id": 22,
"account_level": false,
"payout_type": "Resolution",
"reference": "RES-SRC-A",
"net_channel_payout_in_cents": -3000,
"channel_price_in_cents": null,
"ota_commission_in_cents": null,
"ota_payment_charge_commission_in_cents": null,
"withheld_city_tax_in_cents": null,
"cleaning_fee_in_cents": null
}
],
"allocations": [
{
"type": "booking",
"booking_id": 22,
"total_in_cents": 3000,
"ota_in_cents": 3000,
"internal_fee_in_cents": 0,
"absorbed_by": [
{
"type": "booking",
"booking_id": 21,
"total_in_cents": 3000,
"ota_in_cents": 3000,
"internal_fee_in_cents": 0,
"original_ota_amount_in_cents": 112322
}
]
}
],
"created_at": "2026-07-21T09:14:03.000Z",
"updated_at": "2026-07-21T09:14:03.000Z"
}
]
}