Query Construction Overview

Link to section

Overview

The /v1/load endpoint executes queries against your discovered schema. Unlike traditional REST APIs where you call different endpoints for different resources, you construct a JSON query object that specifies:

  • What to measure (measures)
  • How to slice it (dimensions)
  • What to filter (segments and filters)
  • When to analyze (time dimensions)
  • How to format results (order, limit, offset)

Note

  • For most reporting, query views like Sales and ItemSales rather than raw cubes. Views pre-join data from multiple cubes and pre-filter for common use cases. See Views vs Cubes for details.
  • Complete Query Reference: For detailed information about all query properties and advanced options, see the Cube Query Format documentation.
Link to section

Basic query structure

Every query follows this structure:

Note

All fields are optional except that you must include at least one measure or dimension. However, most useful queries include measures, time dimensions, and segments.

Link to section

Query components

Each component serves a specific purpose in your query:

ComponentPurposeLearn More
MeasuresDefine what to calculate (sums, counts, averages)Measures Guide
DimensionsDefine how to group results (location, channel, customer)Dimensions Guide
Time DimensionsEnable time-series analysis with date groupingTime Dimensions Guide
SegmentsApply predefined business logic filtersSegments Guide
FiltersAdd custom filtering conditionsFilters Guide
Order, Limit, OffsetControl result sorting and paginationOrdering & Pagination
Link to section

Quick start examples

These examples use the Sales view, which is the recommended starting point for most reporting queries. The Sales view pre-filters to closed orders, so no closed_checks segment is needed.

Link to section

Simple Query: Total Sales Today

{ "measures": ["Sales.net_sales"], "timeDimensions": [{ "dimension": "Sales.local_reporting_timestamp", "dateRange": "today" }] }

Returns a single total of all closed sales for today—the simplest query for checking current day revenue.

Link to section

Grouped Query: Sales by Location

{ "measures": ["Sales.net_sales", "Sales.order_count"], "dimensions": ["Sales.location_name"], "timeDimensions": [{ "dimension": "Sales.local_reporting_timestamp", "dateRange": "last 30 days" }] }

Returns total sales and order count for each location over the last 30 days—one row per location showing performance comparison. The Sales view gives you location_name directly.

Link to section

Time-Series Query: Daily Sales Trend

{ "measures": ["Sales.net_sales"], "timeDimensions": [{ "dimension": "Sales.local_reporting_timestamp", "dateRange": ["2024-01-01", "2024-01-31"], "granularity": "day" }], "order": { "Sales.local_reporting_timestamp": "asc" } }

Returns daily sales for each day in January—31 rows showing the sales trend over time in chronological order.

Link to section

Filtered Query: Online Sales Only

{ "measures": ["Sales.net_sales", "Sales.tips_amount"], "dimensions": ["Sales.channel_name"], "timeDimensions": [{ "dimension": "Sales.local_reporting_timestamp", "dateRange": "this month", "granularity": "day" }], "segments": ["Sales.online"] }

Returns daily online sales and tips by channel this month—uses the Sales.online segment to filter to online orders only.

Link to section

Executing queries

Link to section

Using POST (Recommended)

curl -X POST "https://connect.squareup.com/reporting/v1/load" \ -H "Authorization: Bearer ${SQUARE_ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "query": { "measures": ["Sales.net_sales"], "timeDimensions": [{ "dimension": "Sales.local_reporting_timestamp", "dateRange": "today" }] } }'

Warning

POST Body Format: The query must be wrapped in a "query" field. Without this wrapper, you'll receive an error: {"error": "Query param is required"}.

Link to section

Using GET

For simple queries, you can use GET with URL-encoded JSON:

QUERY='{"measures":["Sales.net_sales"],"timeDimensions":[{"dimension":"Sales.local_reporting_timestamp","dateRange":"today"}]}' ENCODED=$(echo $QUERY | jq -sRr @uri) curl -X GET "https://connect.squareup.com/reporting/v1/load?query=${ENCODED}" \ -H "Authorization: Bearer ${SQUARE_ACCESS_TOKEN}"
Link to section

Response Format

Success response with data:

{ "data": [ { "Sales.local_reporting_timestamp.day": "2024-02-05T00:00:00.000", "Sales.net_sales": "1250.50" } ] }

Success response with no data:

{ "data": [] }

Note

Empty Results Are Not Errors: An empty data array means the query executed successfully but found no matching records. This is normal when:

  • The date range has no sales activity
  • Filters are too restrictive
  • The location/channel combination doesn't exist
  • Segments exclude all records

To troubleshoot empty results:

  • Expand the date range (try "last 30 days" instead of "today")
  • Remove or relax filters
  • Verify the location/customer/device IDs exist
  • Check if segments are too restrictive (try without segments first)
  • Use the metadata endpoint to confirm the entities exist

Long-running query:

{ "error": "Continue wait" }

Retry the same request until you get results.

Link to section

Query building best practices

Link to section

1. Use Views for Sales Reports

{ "measures": ["Sales.net_sales"] }

The Sales view pre-filters to closed orders — no segment needed. If querying the Orders cube directly, always add "segments": ["Orders.closed_checks"].

Link to section

2. Specify Explicit Date Ranges

{ "timeDimensions": [{ "dateRange": ["2024-01-01", "2024-01-31"] }] }

Avoid open-ended ranges that might return too much data.

Link to section

3. Set Reasonable Limits

{ "limit": 1000 }

Especially important when using multiple dimensions.

Link to section

4. Validate Before Executing

Check that all measures, dimensions, and segments exist in your metadata before querying.

Link to section

Common mistakes

Link to section

❌ Querying Orders Cube Without Segment

{ "measures": ["Orders.net_sales"] // Missing: "segments": ["Orders.closed_checks"] }

This includes open/unpaid orders, which doesn't match dashboard reports. Use the Sales view instead, which pre-filters to closed orders.

Link to section

❌ No Date Range

{ "timeDimensions": [{ "dimension": "Sales.local_reporting_timestamp" // Missing: "dateRange" }] }

This might return all historical data.

Link to section

❌ Too Many Dimensions Without Limit

{ "dimensions": ["Sales.location_name", "Sales.channel_name", "Sales.employee_full_name"] // Missing: "limit": 1000 }

This could return millions of rows.