Commerce Spine docs
V0 GraphQL surface for agents and automations.

COMMERCE SPINE DATA LAYER

GraphQL API Documentation

Query normalized Amazon data from Commerce Spine through a read-only API designed for agents, scripts, and automations.

GraphQL Read-only Bearer token

Endpoint

The entire collection uses a single route. Behavior is determined by the GraphQL operation sent in the request body.

POST{{baseUrl}}/graphql
39documented operations
10documented entities
90 daysmaximum demonstrated range
JSONContent-Type

Quickstart

Set the URL, token, and an allowed account. Then run your first query.

cURL
curl --request POST '{{baseUrl}}/graphql' \
  --header 'Authorization: Bearer {{bearerToken}}' \
  --header 'Content-Type: application/json' \
  --data '{"query":"query Health { _health { status service timestamp } }"}'
Public health checkThe _health operation does not require a Bearer token.
GraphQL
query Health {
  _health {
    status
    service
    timestamp
  }
}

Authentication

Protected operations use an agent token in the Authorization header. Console session tokens belong to the /api/v1 surface and must not be used here.

AuthorizationBearer cs_live_…
Token scopeThe collection uses an agent token with the data:l2:read scope, including inventory, listing, and Current State reads.
Account scopeThe API applies the intersection of the organization and user scopes. Requesting an account outside that scope returns FORBIDDEN_ACCOUNT_SCOPE.
Auth smoke
query AmazonAccounts {
  amazonAccounts {
    id
    sellerId
  }
}

Without the header, or with an invalid token, this query should return UNAUTHENTICATED.

DISCOVERY

Catalog & accounts

Discover allowed accounts, asset contracts, and the latest available date before building data queries.

amazonAccounts

Lists the Amazon accounts within the organization and user permission scope. Use an id as accountId for data queries.

POST /graphql
GraphQL
query AmazonAccounts {
  amazonAccounts {
    id sellerId marketplaceId marketplaceName marketplaceRegion
    countryCode currencyCode storeName accountType isActive
    connectedAdsApi connectedSellerCentral
  }
}

dataCatalog

Lists available assets and their fields for a catalog layer.

POST /graphql
GraphQL
query DataCatalog($layer: DataLayer) {
  dataCatalog(layer: $layer) {
    id entity layer table dataset description queryable
    accountField dateField
    fields { name type filterable groupable sortable aggregatable }
  }
}
Variables
{"layer":"L2"}
Product asset catalog

This layer lists registered product assets inventory and listing, not the raw source tables.

GraphQL
query DataCatalogL1($layer: DataLayer) {
  dataCatalog(layer: $layer) {
    id entity layer table dataset description queryable
    accountField dateField
    fields { name type filterable groupable sortable aggregatable }
  }
}
Variables
{"layer":"L1"}

dataAsset

Returns the contract for a specific asset by entity name.

POST /graphql
GraphQL
query DataAsset($asset: String!) {
  dataAsset(asset: $asset) {
    id entity layer table dataset description queryable
    accountField dateField
    fields { name type filterable groupable sortable aggregatable }
  }
}
Variables
{"asset":"accountPerformance"}
Inventory asset

The inventory catalog id is inventory.amazon_inventory and its entity key is inventory.

GraphQL
query DataAssetInventory($asset: String!) {
  dataAsset(asset: $asset) {
    id entity layer table dataset description queryable
    accountField dateField
    fields { name type filterable groupable sortable aggregatable }
  }
}
Variables
{"asset":"inventory"}
Listing asset

The listing catalog id is listing.amazon_listing and its entity key is listing. The table is sellercentral_alllistings_report.

GraphQL
query DataAssetListing($asset: String!) {
  dataAsset(asset: $asset) {
    id entity layer table dataset description queryable
    accountField dateField
    fields { name type filterable groupable sortable aggregatable }
  }
}
Variables
{"asset":"listing"}

dataFreshness

Returns the latest available date across assets or for a specific asset.

POST /graphql
GraphQL
query DataFreshness($asset: String) {
  dataFreshness(asset: $asset) {
    asset layer dateField latestReportDate
  }
}
Variables
{"asset":null}
Inventory freshness

Inventory freshness is the maximum last_successful_run_date across the three amazon_sellercentral inventory report modules.

GraphQL
query InventoryFreshness($asset: String) {
  dataFreshness(asset: $asset) {
    asset layer dateField latestReportDate
  }
}
Variables
{"asset":"inventory"}
Listing freshness

Listing freshness is the last_successful_run_date for amazon_sellercentral_alllistings_report only.

GraphQL
query ListingFreshness($asset: String) {
  dataFreshness(asset: $asset) {
    asset layer dateField latestReportDate
  }
}
Variables
{"asset":"listing"}
REFERENCE

Entities

Reporting entities return rows, aggregates in totals, cursors in pageInfo, and metadata in queryInfo. inventory and listing are snapshots; currentState returns the current configuration and status for requested IDs.

10 entities found

accountPerformance

AccountPerformanceInput!

Consolidated daily account performance across advertising, revenue, orders, and total sales.

Fields returned in the collection16 fields
accountIdFIELD
accountNameFIELD
reportDateFIELD
countryCodeFIELD
currencyCodeFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
orderedRevenueFIELD
shippedRevenueFIELD
shippedUnitsFIELD
totalOrderedUnitsFIELD
totalProductSalesFIELD
derivedOBJECT
View full example
GraphQL
query AccountPerformance($input: AccountPerformanceInput!) {
  accountPerformance(input: $input) {
    rows { accountId accountName reportDate countryCode currencyCode adImpressions adClicks }
    totals { adSpend adRevenue orderedRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

productPerformance

ProductPerformanceInput!

Daily performance by product and SKU, including advertising, sales, ratings, and reviews.

Fields returned in the collection18 fields
accountIdFIELD
reportDateFIELD
productFIELD
skuFIELD
productTitleFIELD
countryCodeFIELD
currencyCodeFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
orderedRevenueFIELD
shippedUnitsFIELD
totalProductSalesFIELD
averageRatingFIELD
reviewCountFIELD
derivedOBJECT
View full example
GraphQL
query ProductPerformance($input: ProductPerformanceInput!) {
  productPerformance(input: $input) {
    rows { accountId reportDate product sku productTitle countryCode currencyCode }
    totals { adSpend adRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

campaignPerformance

CampaignPerformanceInput!

Daily campaign performance with status, portfolio, budget, and new-to-brand metrics.

Fields returned in the collection19 fields
accountIdFIELD
reportDateFIELD
campaignIdFIELD
campaignNameFIELD
campaignTypeFIELD
statusFIELD
portfolioIdFIELD
portfolioNameFIELD
countryCodeFIELD
currencyCodeFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
ntbOrdersFIELD
ntbRevenueFIELD
dailyBudgetFIELD
derivedOBJECT
View full example
GraphQL
query CampaignPerformance($input: CampaignPerformanceInput!) {
  campaignPerformance(input: $input) {
    rows { accountId reportDate campaignId campaignName campaignType status portfolioId }
    totals { adSpend adRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

keywordPerformance

KeywordPerformanceInput!

Keyword metrics with match type, bid, campaign, ad group, and brand indicators.

Fields returned in the collection18 fields
accountIdFIELD
reportDateFIELD
keywordIdFIELD
keywordTextFIELD
matchTypeFIELD
keywordStatusFIELD
campaignIdFIELD
campaignNameFIELD
campaignTypeFIELD
adgroupIdFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
currentBidFIELD
isBrandKeywordFIELD
derivedOBJECT
View full example
GraphQL
query KeywordPerformance($input: KeywordPerformanceInput!) {
  keywordPerformance(input: $input) {
    rows { accountId reportDate keywordId keywordText matchType keywordStatus campaignId }
    totals { adSpend adRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

searchTermPerformance

SearchTermPerformanceInput!

Customer search terms linked to the target, campaign, and ad group that captured them.

Fields returned in the collection17 fields
accountIdFIELD
reportDateFIELD
searchTermFIELD
matchTypeFIELD
isAsinFIELD
isBrandTermFIELD
targetFIELD
campaignIdFIELD
campaignNameFIELD
campaignTypeFIELD
adgroupIdFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
derivedOBJECT
View full example
GraphQL
query SearchTermPerformance($input: SearchTermPerformanceInput!) {
  searchTermPerformance(input: $input) {
    rows { accountId reportDate searchTerm matchType isAsin isBrandTerm target }
    totals { adSpend adRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

productTargetPerformance

ProductTargetPerformanceInput!

Product or category target results, including bid, status, and campaign context.

Fields returned in the collection17 fields
accountIdFIELD
reportDateFIELD
targetIdFIELD
targetFIELD
targetStatusFIELD
isBrandTargetFIELD
campaignIdFIELD
campaignNameFIELD
campaignTypeFIELD
adgroupIdFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
currentBidFIELD
derivedOBJECT
View full example
GraphQL
query ProductTargetPerformance($input: ProductTargetPerformanceInput!) {
  productTargetPerformance(input: $input) {
    rows { accountId reportDate targetId target targetStatus isBrandTarget campaignId }
    totals { adSpend adRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

advertisedProductPerformance

AdvertisedProductPerformanceInput!

Advertised products by ASIN/SKU, including ad status and new-to-brand attribution.

Fields returned in the collection19 fields
accountIdFIELD
reportDateFIELD
productAdIdFIELD
productFIELD
skuFIELD
productTitleFIELD
adProductStatusFIELD
campaignIdFIELD
campaignNameFIELD
campaignTypeFIELD
adgroupIdFIELD
adImpressionsFIELD
adClicksFIELD
adOrdersFIELD
adSpendFIELD
adRevenueFIELD
adNtbOrdersFIELD
adNtbRevenueFIELD
derivedOBJECT
View full example
GraphQL
query AdvertisedProductPerformance($input: AdvertisedProductPerformanceInput!) {
  advertisedProductPerformance(input: $input) {
    rows { accountId reportDate productAdId product sku productTitle adProductStatus }
    totals { adSpend adRevenue derived { acos roas } }
    pageInfo { hasNextPage endCursor }
    queryInfo { requestId returnedRows effectiveAccountIds }
  }
}
Variables
{ "input": { "accountIds": ["{{accountId}}"], "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }, "pagination": { "first": {{pageSize}} } } }

currentState

CurrentStateInput!

Returns the current configuration and status of requested campaigns, keywords, automatic targets, or product targets. Send one account, one adProduct (SP, SB, or SD), one asset, and a non-empty list of IDs. adProduct defaults to SP; SB supports campaigns, keywords, and product targets, while SD supports campaigns and product targets.

Fields returned in the collection18 fields
campaignIdFIELD
keywordIdFIELD
targetIdFIELD
nameFIELD
stateFIELD
targetingTypeFIELD
portfolioIdFIELD
startDateFIELD
endDateFIELD
budgetOBJECT
dynamicBiddingOBJECT
adGroupIdFIELD
keywordTextFIELD
matchTypeFIELD
bidFIELD
expressionTypeFIELD
expressionOBJECT
resolvedExpressionOBJECT
Campaign example

Campaign status, budget, dates, portfolio, targeting type, and dynamic-bidding settings.

GraphQL
query CurrentCampaignState($input: CurrentStateInput!) {
  currentState(input: $input) {
    accountId
    asset
    items {
      __typename
      ... on CampaignCurrentState {
        campaignId name state targetingType portfolioId startDate endDate
        budget { budgetType budget }
        dynamicBidding { strategy placementBidding { placement percentage } }
      }
    }
  }
}
Variables
{
  "input": {
    "accountId": "{{accountId}}",
    "adProduct": "SP",
    "asset": "CAMPAIGN",
    "ids": ["campaign-id"]
  }
}
Keyword example

Keyword text, match type, status, bid, and parent campaign and ad-group IDs.

GraphQL
query CurrentKeywordState($input: CurrentStateInput!) {
  currentState(input: $input) {
    accountId
    asset
    items {
      __typename
      ... on KeywordCurrentState {
        keywordId campaignId adGroupId keywordText matchType state bid
      }
    }
  }
}
Variables
{
  "input": {
    "accountId": "{{accountId}}",
    "adProduct": "SB",
    "asset": "KEYWORD",
    "ids": ["keyword-id"]
  }
}
Automatic target example

Automatic-target status, bid, expressions, and parent campaign and ad-group IDs.

GraphQL
query CurrentTargetState($input: CurrentStateInput!) {
  currentState(input: $input) {
    accountId
    asset
    items {
      __typename
      ... on TargetCurrentState {
        targetId campaignId adGroupId expressionType
        expression { type value }
        resolvedExpression { type value }
        state bid
      }
    }
  }
}
Variables
{
  "input": {
    "accountId": "{{accountId}}",
    "adProduct": "SP",
    "asset": "TARGET",
    "ids": ["target-id"]
  }
}
Product target example

Manual product-target status, bid, expressions, and parent campaign and ad-group IDs.

GraphQL
query CurrentProductTargetState($input: CurrentStateInput!) {
  currentState(input: $input) {
    accountId
    asset
    items {
      __typename
      ... on ProductTargetCurrentState {
        targetId campaignId adGroupId expressionType
        expression { type value }
        resolvedExpression { type value }
        state bid
      }
    }
  }
}
Variables
{
  "input": {
    "accountId": "{{accountId}}",
    "adProduct": "SD",
    "asset": "PRODUCT_TARGET",
    "ids": ["product-target-id"]
  }
}

inventory

InventoryInput!

Current stock snapshot. The engine pins the latest report_date for each account, so the input has no dateRange. Prefer a single accountId.

No date rangeRequests select the pinned snapshot per account. Use dataFreshness with the inventory asset to read the snapshot date.
Bytes billedSelecting nests loads the Manage FBA and Restock reports. Query the root fields only when you are checking bytesProcessed.
DefaultsTotals sum the base quantity only. Without orderBy, rows sort by accountId ascending then sku ascending.
Base row fields12 fields
accountIdFIELD
sellerIdFIELD
accountNameFIELD
countryCodeFIELD
currencyCodeFIELD
asinFIELD
skuFIELD
quantityFIELD
priceFIELD
businessPriceFIELD
reportDateFIELD
downloadDateFIELD
Nested selections11 objects
fbaInventoryOBJECT
fbaInboundInventoryOBJECT
merchantFulfilledInventoryOBJECT
fbaDateControlsOBJECT
productIdentificationOBJECT
availableAndTotalInventoryOBJECT
fulfillmentCenterInventoryOBJECT
inboundShipmentsOBJECT
salesCoverageAndReplenishmentOBJECT
inventoryThresholdsOBJECT
restockDateControlsOBJECT

A nest resolves to null when its report has no matching row. The root asin is not the same value as productIdentification.asin.

View the fields inside each nest
Manage FBA report
fbaInventorywarehouseQuantity fulfillableQuantity reservedQuantity unsellableQuantity totalQuantity researchingQuantity reservedFutureSupply futureSupplyBuyable
fbaInboundInventoryworkingQuantity shippedQuantity receivingQuantity
merchantFulfilledInventorylistingExists fulfillableQuantity
fbaDateControlsreportDate downloadDate
Restock report
productIdentificationasin productName condition fulfilledBy supplier supplierPartNo
availableAndTotalInventoryavailable totalUnits customerOrder unfulfillable
fulfillmentCenterInventoryfcProcessing fcTransfer
inboundShipmentsinbound working shipped receiving
salesCoverageAndReplenishmentunitsSoldLast30Days salesLast30Days daysOfSupply daysOfSupplyAtAmazon totalDaysOfSupply recommendedReplenishmentQty recommendedShipDate alert maximumShipmentQuantity utilization unitStorageSize
inventoryThresholdscurrentMonthVeryLow currentMonthMinimum currentMonthMaximum currentMonthVeryHigh nextMonthVeryLow nextMonthMinimum nextMonthMaximum nextMonthVeryHigh
restockDateControlsreportDate downloadDate
Root only

Lightest selection: no nests and no totals. Prefer it when checking bytes billed.

GraphQL
query InventoryRootOnly($input: InventoryInput!) {
  inventory(input: $input) {
    rows { accountId sku quantity asin reportDate }
    pageInfo { hasNextPage endCursor }
    queryInfo {
      requestId sourceAsset layer returnedRows
      maximumBytesBilled bytesProcessed effectiveAccountIds
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Root with totals

Full base row plus aggregates. Select totals only when you need them.

GraphQL
query InventoryRootWithTotals($input: InventoryInput!) {
  inventory(input: $input) {
    rows {
      accountId sellerId accountName countryCode currencyCode
      asin sku quantity price businessPrice reportDate downloadDate
    }
    totals { quantity }
    pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
    queryInfo {
      requestId sourceAsset layer returnedRows maximumBytesBilled
      bytesProcessed effectiveAccountIds dateFrom dateTo generatedAt
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Filtered and sorted

Filters and sorting apply to root and base fields only.

GraphQL
query InventoryFiltered($input: InventoryInput!) {
  inventory(input: $input) {
    rows { accountId sku asin countryCode quantity price reportDate }
    totals { quantity }
    pageInfo { hasNextPage endCursor }
    queryInfo {
      layer sourceAsset effectiveAccountIds returnedRows bytesProcessed
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "where": {
      "countryCode": { "eq": "US" },
      "quantity": { "gte": 1 }
    },
    "orderBy": [
      { "field": "quantity", "direction": "DESC" },
      { "field": "sku", "direction": "ASC" }
    ],
    "pagination": { "first": {{pageSize}} }
  }
}
Manage FBA nests

Selecting these nests loads the Manage FBA inventory report. A missing join returns a null nest.

GraphQL
query InventoryWithFba($input: InventoryInput!) {
  inventory(input: $input) {
    rows {
      accountId sku asin quantity
      fbaInventory {
        warehouseQuantity fulfillableQuantity reservedQuantity
        unsellableQuantity totalQuantity researchingQuantity
        reservedFutureSupply futureSupplyBuyable
      }
      fbaInboundInventory { workingQuantity shippedQuantity receivingQuantity }
      merchantFulfilledInventory { listingExists fulfillableQuantity }
      fbaDateControls { reportDate downloadDate }
    }
    totals { quantity }
    pageInfo { hasNextPage endCursor }
    queryInfo { layer sourceAsset returnedRows bytesProcessed }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Restock nests

Selecting these nests loads the Restock inventory report.

GraphQL
query InventoryWithRestock($input: InventoryInput!) {
  inventory(input: $input) {
    rows {
      accountId sku asin quantity
      productIdentification {
        asin productName condition fulfilledBy supplier supplierPartNo
      }
      availableAndTotalInventory {
        available totalUnits customerOrder unfulfillable
      }
      fulfillmentCenterInventory { fcProcessing fcTransfer }
      inboundShipments { inbound working shipped receiving }
      salesCoverageAndReplenishment {
        unitsSoldLast30Days salesLast30Days daysOfSupply
        daysOfSupplyAtAmazon totalDaysOfSupply
        recommendedReplenishmentQty recommendedShipDate alert
        maximumShipmentQuantity utilization unitStorageSize
      }
      inventoryThresholds {
        currentMonthVeryLow currentMonthMinimum
        currentMonthMaximum currentMonthVeryHigh
        nextMonthVeryLow nextMonthMinimum
        nextMonthMaximum nextMonthVeryHigh
      }
      restockDateControls { reportDate downloadDate }
    }
    totals { quantity }
    pageInfo { hasNextPage endCursor }
    queryInfo { layer sourceAsset returnedRows bytesProcessed }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Base, FBA and Restock together

This selection loads all three tables and is heavier than root only.

GraphQL
query InventoryFull($input: InventoryInput!) {
  inventory(input: $input) {
    rows {
      accountId sku asin quantity price
      fbaInboundInventory { workingQuantity shippedQuantity receivingQuantity }
      productIdentification { asin productName }
      inventoryThresholds { currentMonthMinimum currentMonthMaximum }
      inboundShipments { inbound working shipped receiving }
    }
    totals { quantity }
    pageInfo { hasNextPage endCursor }
    queryInfo {
      requestId layer sourceAsset returnedRows
      effectiveAccountIds bytesProcessed maximumBytesBilled
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Next page

Send the previous endCursor as after. The cursor is an opaque offset cursor.

GraphQL
query InventoryPage2($input: InventoryInput!) {
  inventory(input: $input) {
    rows { accountId sku quantity }
    pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
    queryInfo { returnedRows bytesProcessed }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": {
      "first": {{pageSize}},
      "after": "{{pageCursor}}"
    }
  }
}

listing

ListingInput!

Current All Listings Report snapshot. The engine pins the latest report_date for each account, so the input has no dateRange. Prefer a single accountId.

No date rangeRequests select the pinned snapshot per account. Use dataFreshness with the listing asset to read the snapshot date.
Bytes billedSelecting itemDetail loads sellercentral_listings_item_detail. Query the root fields only when you are checking bytesProcessed.
DefaultsTotals sum quantity and pendingQuantity only. Without orderBy, rows sort by accountId ascending then sku ascending.
Base row fields28 fields
accountIdFIELD
accountNameFIELD
currencyCodeFIELD
listingIdFIELD
skuFIELD
asinFIELD
asin2FIELD
asin3FIELD
itemNameFIELD
itemDescriptionFIELD
priceFIELD
quantityFIELD
pendingQuantityFIELD
openDateFIELD
imageUrlFIELD
itemIsMarketplaceFIELD
productIdTypeFIELD
productIdFIELD
itemNoteFIELD
itemConditionFIELD
willShipInternationallyFIELD
expeditedShippingFIELD
fulfillmentChannelFIELD
merchantShippingGroupFIELD
statusFIELD
addDeleteFIELD
reportDateFIELD
downloadDateFIELD
Nested selections1 object
itemDetailOBJECT

itemDetail resolves to null when its report has no matching row. The nest does not repeat asin, sku, or accountId because those already exist on the root.

View the fields inside itemDetail
itemDetailsellerId description featureBulletCount updatedDate etlLoadedAt
Root only

Lightest selection: no itemDetail nest and no totals. Prefer it when checking bytes billed.

GraphQL
query ListingRootOnly($input: ListingInput!) {
  listing(input: $input) {
    rows { accountId sku listingId asin itemName quantity status reportDate }
    pageInfo { hasNextPage endCursor }
    queryInfo {
      requestId sourceAsset layer returnedRows
      maximumBytesBilled bytesProcessed effectiveAccountIds
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Root with totals

Full base row plus aggregates. Select totals only when you need them.

GraphQL
query ListingRootWithTotals($input: ListingInput!) {
  listing(input: $input) {
    rows {
      accountId accountName currencyCode listingId sku asin asin2 asin3
      itemName itemDescription price quantity pendingQuantity openDate imageUrl
      itemIsMarketplace productIdType productId itemNote itemCondition
      willShipInternationally expeditedShipping fulfillmentChannel
      merchantShippingGroup status addDelete reportDate downloadDate
    }
    totals { quantity pendingQuantity }
    pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
    queryInfo {
      requestId sourceAsset layer returnedRows maximumBytesBilled
      bytesProcessed effectiveAccountIds dateFrom dateTo generatedAt
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Filtered and sorted

Filters and sorting apply to root and base fields only.

GraphQL
query ListingFiltered($input: ListingInput!) {
  listing(input: $input) {
    rows {
      accountId sku listingId asin itemName quantity price status
      fulfillmentChannel reportDate
    }
    totals { quantity pendingQuantity }
    pageInfo { hasNextPage endCursor }
    queryInfo {
      layer sourceAsset effectiveAccountIds returnedRows bytesProcessed
    }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "where": {
      "status": { "eq": "Active" },
      "fulfillmentChannel": { "eq": "DEFAULT" }
    },
    "orderBy": [
      { "field": "quantity", "direction": "DESC" },
      { "field": "sku", "direction": "ASC" }
    ],
    "pagination": { "first": {{pageSize}} }
  }
}
itemDetail nest

Selecting itemDetail loads sellercentral_listings_item_detail. A missing join returns null.

GraphQL
query ListingWithItemDetail($input: ListingInput!) {
  listing(input: $input) {
    rows {
      accountId sku listingId asin itemName itemDescription price quantity
      status fulfillmentChannel
      itemDetail {
        sellerId description featureBulletCount updatedDate etlLoadedAt
      }
    }
    totals { quantity pendingQuantity }
    pageInfo { hasNextPage endCursor }
    queryInfo { layer sourceAsset returnedRows bytesProcessed }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": { "first": {{pageSize}} }
  }
}
Next page

Send the previous endCursor as after. The cursor is an opaque offset cursor.

GraphQL
query ListingPage2($input: ListingInput!) {
  listing(input: $input) {
    rows { accountId sku listingId quantity }
    pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
    queryInfo { returnedRows bytesProcessed }
  }
}
Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "pagination": {
      "first": {{pageSize}},
      "after": "{{pageCursor}}"
    }
  }
}
ADVANCED QUERIES

Filters & sorting

The official example combines where, orderBy, and pagination in campaignPerformance.

Variables
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" },
    "where": {
      "campaignType": { "eq": "sponsoredProducts" },
      "adSpend": { "gte": "1" }
    },
    "orderBy": [{ "field": "adSpend", "direction": "DESC" }],
    "pagination": { "first": {{pageSize}} }
  }
}
All allowed accountsOmitting accountIds automatically uses the complete set of authorized accounts.

inventory and listing also accept where and orderBy on their root and base fields, without dateRange.

Pagination & response envelope

Use first for the page size, then send after with the returned endCursor to advance. The collection stores that value in the pageCursor variable.

GraphQL
query AccountPerformance($input: AccountPerformanceInput!) {
  accountPerformance(input: $input) {
    rows { accountId reportDate adSpend adRevenue }
    pageInfo { hasNextPage hasPreviousPage startCursor endCursor }
    queryInfo {
      requestId layer sourceAsset dateFrom dateTo
      effectiveAccountIds returnedRows maximumBytesBilled
      bytesProcessed generatedAt
    }
  }
}

Expected errors

Errors follow the GraphQL format and expose a code at errors[].extensions.code.

CodeWhen it occursHow to handle it
UNAUTHENTICATEDMissing header or invalid token.Check the agent token.
FORBIDDEN_ACCOUNT_SCOPEAccount outside the allowed scope.Use an ID returned by amazonAccounts.
DATE_RANGE_TOO_LARGEDate range longer than 90 days.Split the period into smaller windows.
VALIDATION_ERRORCurrent State receives an empty ids list.Send at least one entity ID.
ACTION_ACCOUNT_NOT_READYThe selected account is unavailable for this query.Check the account's availability and permissions.
DATA_LAYER_UNAVAILABLEThe Current State request cannot be completed.Retry after the supplied delay, when present.
Forbidden scope
{
  "input": {
    "accountIds": ["amz_not_in_scope"],
    "dateRange": { "from": "{{dateFrom}}", "to": "{{dateTo}}" }
  }
}
Range over 90 days
{
  "input": {
    "accountIds": ["{{accountId}}"],
    "dateRange": { "from": "2026-01-01", "to": "2026-06-01" }
  }
}
Commerce Spine API — GraphQL Documentation