---
title: "Order-level P&L detail"
method: POST
path: "/pnl/orders"
tags: ["P&L"]
---

# Order-level P&L detail

`POST /pnl/orders`

One row per order x SKU with its fee breakdown, filterable by order source, settled state, product or SKU — the same filters applied by hand to the Seller Center export. Unsettled lines are included by default and their amounts still move.

## Request body

- PnlOrdersRequest — POST /pnl/orders request body — order x SKU detail.
  - `start_date` string, date, nullable — Inclusive paid-date window start.
  - `end_date` string, date, nullable — Inclusive paid-date window end.
  - `order_source` 'Video' | 'Product card' | 'Live', nullable — Filter by TikTok's own order-source value.
  - `settled` boolean, nullable — True = only settled orders, False = only unsettled. Unsettled amounts still move as TikTok settles them.
  - `product_id` string, nullable — Filter to one product.
  - `sku_id` string, nullable — Filter to one SKU.
  - `limit` integer — Page size.
  - `offset` integer — Page offset.
  - `amounts_fields` union — Which fee columns each row carries. `standard` (default) is the 12 lines a P&L waterfall needs. `full` is all 61 TikTok ships — coupons, co-funded creator bonuses, campaign and FBT fees, shipping detail and taxes. Or pass an explicit list of field names to take only what you need. Unknown names are rejected rather than ignored, so a typo cannot read as a zero fee. The resolved list comes back as `selected_fields`.
    - 'standard' | 'full'
    - string[]

## Response `200`

Successful Response

- PnlOrdersResponse — Paginated order x SKU detail.
  - `shop_id` integer, required
  - `seller_id` string, required
  - `total` integer, required
  - `limit` integer, required
  - `offset` integer, required
  - `selected_fields` string[] — The fee columns every row in this page carries, in canonical order. Echoed once per page, not per row: it is provenance for the projection you asked for, so an absent key can be read as 'not requested' rather than 'no data'.
  - `orders` PnlOrderLineOut[], required
    - `order_id` string, required
    - `sku_id` string, required
    - `product_id` string, nullable
    - `product_name` string, nullable
    - `sku_name` string, nullable
    - `quantity` integer, nullable
    - `order_paid_date` string, nullable
    - `order_settled_date` string, nullable
    - `order_status` string, nullable
    - `order_source` string[] — TikTok models this as a list, e.g. ["Video"].
    - `is_settled` boolean, required
    - `unsettled_reason` string, nullable — Why TikTok has not settled this line yet.
    - `estimated_settle_time` string, nullable — Free text from TikTok, e.g. "Delivery + 1 days" — not a timestamp.
    - `sample_order_type` string, nullable
    - `linked_statement_id` string, nullable — Settlement statement this line was paid on; null until settled.
    - `currency` string, required
    - `amounts` PnlOrderAmounts, required — The fee columns this row carries, keyed by TikTok's own column names. An open map rather than a fixed field set, because the caller picks the projection: a fixed model would advertise fields a given response deliberately omits. The keys present are exactly ``selected_fields`` on the page. ``null`` means TikTok sent no value for that column — it is NOT zero, and a key that is absent entirely means you did not ask for it. Signs are TikTok's own: ``gross_sales`` positive, cost lines negative.
  - `data_status` PnlDataStatus, required — Freshness and reachability of this shop's P&L data. ``state`` distinguishes "no sales" from "we cannot read the finance export": ``no_permission`` means the shop's Seller Center account lacks finance-tab access and the fix is customer-side, not a retry.
    - `state` string, required — Latest export-run status: never_run | pending | parsed | empty | failed | no_permission.
    - `last_synced_at` string, nullable — ISO timestamp of the newest successfully parsed run.
    - `last_window` PnlDateWindow — The date window an export run requested.
      - `start_date` string, nullable
      - `end_date` string, nullable

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/reacherapp/apis/reacher-data-api.md) · [All operations](https://skmtc.dev/reacherapp/apis/reacher-data-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/reacherapp/reacher-data-api/revisions/5eefff009b5b/schema)
