P&L

Per-SKU gross / contribution P&L

Changed on

One row per SKU: units sold and the fee lines from the order-level export summed over the window, joined to your cost of goods, with a gross profit and margin.

This is a GROSS / CONTRIBUTION view, not a net bottom line. The fees here are the ones TikTok books against the order itself — referral, affiliate commission, refunds, discounts and the like — and ad spend is NOT among them: TikTok does not attribute ad spend to a single SKU, so gross_profit is revenue less those per-SKU fees less COGS, and stops one step short of net earnings. For the true shop-level bottom line that includes ad spend, use POST /pnl/summary and POST /pnl/profit. If you request the net_earnings or total_expense columns they are the order-line totals and likewise exclude ad spend.

gross_profit is an upper bound while units_uncosted is non-zero — uncosted units are counted, never assumed free. Windowed by order PAID date; single shop only.

post/pnl/skus

Request

  • Base URL
    https://api.reacherapp.com/public/v1
  • URL
    https://api.reacherapp.com/public/v1/pnl/skus
  • Auth
    API key in header x-api-key and API key in header x-shop-id

Request body

start_datestring date nullable

Inclusive paid-date window start (YYYY-MM-DD).

end_datestring date nullable

Inclusive paid-date window end (YYYY-MM-DD).

product_idstring nullable

Filter to one product.

sku_idstring nullable

Filter to one SKU.

limitinteger

Page size (SKUs per page).

offsetinteger

Page offset.

sort'gross_sales' | 'gross_profit' | 'units'

Sort key, always descending, tie-broken by product_id then sku_id so paging is stable. gross_sales (default) surfaces top sellers, gross_profit top contributors, units highest volume.

Response

Successful Response

shop_idinteger required
seller_idstring required
currencystring required
start_datestring required
end_datestring required
totalinteger required

Distinct SKUs matching the window and filters, before paging.

limitinteger required
offsetinteger required
selected_fieldsstring[]

The fee columns every SKU's amounts carries, in canonical order — provenance for the projection you asked for, so an absent key reads as 'not requested' rather than 'no data'.

currency_mismatched_costsinteger required

COGS rows skipped because they are priced in a different currency than the shop. Non-zero means some SKUs' COGS is silently absent, so their gross_profit is overstated and units_uncosted under-counts.

Changes

    • breaking

      the / response's property type changed from string to no type for status

    • info

      added subschema #1 subschema #2 to the / response property anyOf list for the response status

    • info

      endpoint added