Performance by location

Overview

Get a row per location in the account. Only locations with reviews in the period get a row.

Use this to compare locations.

You'll need a token and a date range.

Returns one row per location, 10 per page unless you set limit.

Prerequisites

  • A bearer token. See Authentication.
  • A date range (range_start, range_end), both Y-m-d H:i:s.
  • Optional: a location id (store_id). Leave it out to report on every location your token can see.

Base URL

EnvironmentURL
Productionhttps://production-api.shoutaboutus.com
Developmenthttps://development-api.shoutaboutus.com

Endpoint

POST /api/v1/reports/response/locationlist

Authentication

Partner or Account token

  • store_id must be inside your own account tree; otherwise 422.
  • Without store_id, the report covers every location the token can see: every location under the partner for a Partner token, the account's locations for an Account token, or only the assigned locations for a user limited to some locations.
  • There are no account_id or client_* fields here; to report on one account under a partner, see Headline numbers or the partner reports.

Rate limit

This endpoint has no rate limit.

Request parameters

None.

Request body

FieldTypeRequiredDescription
range_startstringYesStart of the period, Y-m-d H:i:s (e.g. 2026-01-01 00:00:00). A date without a time is rejected.
range_endstringYesEnd of the period, Y-m-d H:i:s (e.g. 2026-09-30 23:59:59).
store_idintegerNoOne location to report on. Must exist and be inside your account tree. Leave it out to cover every location your token can see.
sort_fieldstringNoColumn to sort by: location_name, total_reviews, total_responses, avg_resp_time, avg_rating, response_rate. Default location_name.
sort_bystringNoSort direction: asc or desc (either case). Default ASC.
search_fieldstringNoField to search. Only location_name. Used together with search_value.
search_valuestringNoText to search for. Matches locations whose name, store code or client_location_id contains it. Applies only when search_field is also sent.
limitintegerNoRows per page, 10 to 100. Values below 10 are raised to 10; above 100 returns 422. Default 10.
pageintegerNoPage number, from 1. Default 1.

Request payload

{
  "range_start": "2026-01-01 00:00:00",
  "range_end": "2026-09-30 23:59:59",
  "sort_field": "total_reviews",
  "sort_by": "desc",
  "limit": 10,
  "page": 1
}

Response body

The rows are in data, with the page links in links and the paging details in meta.

FieldTypeDescription
data[]array of objectsOne row per location with reviews in the period.
data[].idintegerThe location's id (store_id).
data[].location_namestringThe location's name, then - and its client_location_id (or its store code when that's empty).
data[].total_reviewsintegerReviews in the period.
data[].total_responsesintegerResponses submitted for the period's reviews.
data[].avg_resp_timenumberAverage time to respond, in days. 0 when there are no responses.
data[].avg_ratingnumberAverage star rating of the period's reviews.
data[].response_ratenumberPercentage of the period's reviews with a response. Failed responses (no login saved, login error, not responding, business already responded) don't count.
linksobjectPage links.
links.firststringURL of the first page.
links.laststringURL of the last page.
links.prevstring or nullURL of the previous page; null on the first page.
links.nextstring or nullURL of the next page; null on the last page.
metaobjectPaging details.
meta.current_pageintegerThis page's number.
meta.frominteger or nullPosition of the first row on this page; null when the page is empty.
meta.last_pageintegerNumber of the last page.
meta.links[]array of objectsPager links: previous, each page number, next.
meta.links[].urlstring or nullURL of that page; null when there is no such page.
meta.links[].labelstringLink text: a page number, « Previous or Next ».
meta.links[].pageinteger or nullPage number the link goes to; null when there is no such page.
meta.links[].activebooleantrue for the current page.
meta.pathstringURL of this endpoint, without query string.
meta.per_pageintegerRows per page (limit).
meta.tointeger or nullPosition of the last row on this page; null when the page is empty.
meta.totalintegerRows across all pages.

Response payload

{
  "data": [
    {
      "id": 3007,
      "location_name": "Acme Coffee - docs-test-loc-001",
      "total_reviews": 223,
      "total_responses": 0,
      "avg_resp_time": 0,
      "avg_rating": 4.4,
      "response_rate": 0
    }
  ],
  "links": {
    "first": "https://production-api.shoutaboutus.com/api/v1/reports/response/locationlist?page=1",
    "last": "https://production-api.shoutaboutus.com/api/v1/reports/response/locationlist?page=1",
    "prev": null,
    "next": null
  },
  "meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 1,
    "links": [
      {
        "url": null,
        "label": "« Previous",
        "page": null,
        "active": false
      },
      {
        "url": "https://production-api.shoutaboutus.com/api/v1/reports/response/locationlist?page=1",
        "label": "1",
        "page": 1,
        "active": true
      },
      {
        "url": null,
        "label": "Next »",
        "page": null,
        "active": false
      }
    ],
    "path": "https://production-api.shoutaboutus.com/api/v1/reports/response/locationlist",
    "per_page": 10,
    "to": 1,
    "total": 1
  }
}

Examples

Success payload

See Response payload.

Error payload

422 Dates missing

{
  "message": "The range start field is required. (and 1 more error)",
  "errors": {
    "range_start": [
      "The range start field is required."
    ],
    "range_end": [
      "The range end field is required."
    ]
  }
}

422 Date not in Y-m-d H:i:s

{
  "message": "The range start field must match the format Y-m-d H:i:s.",
  "errors": {
    "range_start": [
      "The range start field must match the format Y-m-d H:i:s."
    ]
  }
}

422 Location outside your tree

{
  "message": "The selected store id does not belong to your company hierarchy.",
  "errors": {
    "store_id": [
      "The selected store id does not belong to your company hierarchy."
    ]
  }
}

422 Unknown sort_field

{
  "message": "The selected sort field is invalid.",
  "errors": {
    "sort_field": [
      "The selected sort field is invalid."
    ]
  }
}

422 limit above 100

{
  "message": "The limit field must not be greater than 100.",
  "errors": {
    "limit": [
      "The limit field must not be greater than 100."
    ]
  }
}
StatusMeaning
200One page of location rows.
401The token is missing, expired or invalid.
422A date is missing or not Y-m-d H:i:s, store_id doesn't exist or is outside your tree, a sort or search value isn't allowed, or limit is above 100.
500Unexpected server error.

Example request

curl --request POST \
  --url "https://production-api.shoutaboutus.com/api/v1/reports/response/locationlist" \
  --header 'Authorization: Bearer <bearer-token>' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"range_start": "2026-01-01 00:00:00", "range_end": "2026-09-30 23:59:59", "sort_field": "total_reviews", "sort_by": "desc", "limit": 10, "page": 1}'

Did this page help you?